Jlm
Loading...
Searching...
No Matches
MemoryConverterTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 Magnus Sjalander <work@sjalander.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
12#include <jlm/hls/ir/hls.hpp>
17#include <jlm/rvsdg/theta.hpp>
18#include <jlm/rvsdg/view.hpp>
20
21TEST(MemoryConverterTests, TestTraceArgument)
22{
23 using namespace jlm::llvm;
24 using namespace jlm::hls;
25
26 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
27
28 // Setup the function
29 std::cout << "Function Setup" << std::endl;
30 auto functionType = jlm::rvsdg::FunctionType::Create(
34 MemoryStateType::Create() },
35 { MemoryStateType::Create() });
36
38 rvsdgModule->Rvsdg().GetRootRegion(),
39 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
40
41 // Load followed by store
42 auto loadAddress = lambda->GetFunctionArguments()[0];
43 auto memoryStateArgument = lambda->GetFunctionArguments()[3];
44 auto loadOutput = LoadNonVolatileOperation::Create(
45 loadAddress,
46 { memoryStateArgument },
48 32);
49
50 auto storeAddress = lambda->GetFunctionArguments()[1];
51 auto storeData = lambda->GetFunctionArguments()[2];
52 auto storeOutput =
53 StoreNonVolatileOperation::Create(storeAddress, storeData, { loadOutput[1] }, 32);
54
55 auto lambdaOutput = lambda->finalize({ storeOutput[0] });
56 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
57
58 // Act
59 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
60 const auto tracedPointerNodesVector = TracePointerArguments(lambda);
61 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
62
63 // Assert
64 EXPECT_EQ(tracedPointerNodesVector.size(), 2u); // 2 pointer arguments
65 EXPECT_EQ(tracedPointerNodesVector[0].loadNodes.size(), 1u); // 1 load for the first pointer
66 EXPECT_EQ(tracedPointerNodesVector[0].storeNodes.size(), 0u); // 0 store for the first pointer
67 EXPECT_EQ(
68 tracedPointerNodesVector[0].decoupleNodes.size(),
69 0u); // 0 decouple for the first pointer
70 EXPECT_EQ(tracedPointerNodesVector[1].loadNodes.size(), 0u); // 0 load for the first pointer
71 EXPECT_EQ(tracedPointerNodesVector[1].storeNodes.size(), 1u); // 1 store for the second pointer
72 EXPECT_EQ(tracedPointerNodesVector[1].decoupleNodes.size(), 0u); // 0 load for the first pointer
73}
74
75TEST(MemoryConverterTests, TestLoad)
76{
77 using namespace jlm::llvm;
78 using namespace jlm::hls;
79
80 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
81
82 // Setup the function
83 std::cout << "Function Setup" << std::endl;
84 auto functionType = jlm::rvsdg::FunctionType::Create(
85 { jlm::llvm::PointerType::Create(), MemoryStateType::Create() },
86 { jlm::rvsdg::BitType::Create(32), MemoryStateType::Create() });
87
89 rvsdgModule->Rvsdg().GetRootRegion(),
90 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
91
92 // Single load
93 auto loadAddress = lambda->GetFunctionArguments()[0];
94 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
95 auto loadOutput = LoadNonVolatileOperation::Create(
96 loadAddress,
97 { memoryStateArgument },
99 32);
100
101 auto lambdaOutput = lambda->finalize({ loadOutput[0], loadOutput[1] });
102 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
103
104 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
105
106 // Act
108 MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
109
110 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
111
112 // Memory Converter replaces the lambda so we start from the root of the graph
113 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
114 EXPECT_EQ(region->numNodes(), 1u);
115 lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
116
117 // Assert
118 auto lambdaRegion = lambda->subregion();
119 EXPECT_EQ(lambdaRegion->numNodes(), 3u);
120 EXPECT_EQ(lambdaRegion->narguments(), 3u);
121 EXPECT_EQ(lambdaRegion->nresults(), 3u);
122
123 // Memory state
124 EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(1)->origin()->Type()));
125
126 // Load Address
127 auto loadNode =
128 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
129 EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
130
131 // Load Data
132 loadNode =
133 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
134 EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
135
136 // Request Node
137 auto requestNode =
138 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
139 EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
140
141 // Response Node
142 auto responseNode =
143 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(loadNode->input(2)->origin())->node();
144 EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
145
146 // Response source
147 auto responseSource = responseNode->input(0)->origin();
148 auto regionArgument = jlm::util::assertedCast<jlm::rvsdg::RegionArgument>(responseSource);
149 EXPECT_EQ(regionArgument->index(), 2u);
150}
151
152TEST(MemoryConverterTests, TestStore)
153{
154 using namespace jlm::llvm;
155 using namespace jlm::hls;
156
157 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
158
159 // Setup the function
160 std::cout << "Function Setup" << std::endl;
161 auto functionType = jlm::rvsdg::FunctionType::Create(
164 MemoryStateType::Create() },
165 { MemoryStateType::Create() });
166
167 auto lambda = jlm::rvsdg::LambdaNode::Create(
168 rvsdgModule->Rvsdg().GetRootRegion(),
169 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
170
171 // Single load
172 auto storeAddress = lambda->GetFunctionArguments()[0];
173 auto storeData = lambda->GetFunctionArguments()[1];
174 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
175 auto storeOutput =
176 StoreNonVolatileOperation::Create(storeAddress, storeData, { memoryStateArgument }, 32);
177
178 auto lambdaOutput = lambda->finalize({ storeOutput[0] });
179 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
180
181 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
182
183 // Act
185 MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
186
187 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
188
189 // Memory Converter replaces the lambda so we start from the root of the graph
190 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
191 EXPECT_EQ(region->numNodes(), 1u);
192 lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
193
194 // Assert
195 auto lambdaRegion = lambda->subregion();
196 EXPECT_EQ(lambdaRegion->numNodes(), 4u);
197 EXPECT_EQ(lambdaRegion->narguments(), 4u);
198 EXPECT_EQ(lambdaRegion->nresults(), 2u);
199
200 EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(0)->origin()->Type()));
201 auto bufferNode =
202 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
203 auto storeNode =
204 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(bufferNode->input(0)->origin())->node();
205 EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
206 auto requestNode =
207 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
208 EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
209
210 // Request source
211 auto requestSource = requestNode->input(0)->origin();
212 storeNode = jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(requestSource)->node();
213 EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
214}
215
216TEST(MemoryConverterTests, TestLoadStore)
217{
218 using namespace jlm::llvm;
219 using namespace jlm::hls;
220
221 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
222
223 // Setup the function
224 std::cout << "Function Setup" << std::endl;
225 auto functionType = jlm::rvsdg::FunctionType::Create(
228 MemoryStateType::Create() },
229 { MemoryStateType::Create() });
230
231 auto lambda = jlm::rvsdg::LambdaNode::Create(
232 rvsdgModule->Rvsdg().GetRootRegion(),
233 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
234
235 // Load followed by store
236 auto loadAddress = lambda->GetFunctionArguments()[0];
237 auto storeData = lambda->GetFunctionArguments()[1];
238 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
239 auto loadOutput = LoadNonVolatileOperation::Create(
240 loadAddress,
241 { memoryStateArgument },
243 32);
244 auto storeOutput =
245 StoreNonVolatileOperation::Create(loadOutput[0], storeData, { loadOutput[1] }, 32);
246
247 auto lambdaOutput = lambda->finalize({ storeOutput[0] });
248 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
249
250 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
251
252 // Act
254 MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
255
256 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
257
258 // Memory Converter replaces the lambda so we start from the root of the graph
259 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
260 EXPECT_EQ(region->numNodes(), 1u);
261 lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
262
263 // Assert
264 auto lambdaRegion = lambda->subregion();
265 EXPECT_EQ(lambdaRegion->numNodes(), 7u);
266 EXPECT_EQ(lambdaRegion->narguments(), 5u);
267 EXPECT_EQ(lambdaRegion->nresults(), 3u);
268
269 std::cout << lambdaRegion->result(0)->origin()->Type()->debug_string() << std::endl;
270 EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(0)->origin()->Type()));
271 auto bufferNode =
272 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
273 auto storeNode =
274 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(bufferNode->input(0)->origin())->node();
275 EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
276 auto firstRequestNode =
277 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
278 EXPECT_TRUE(is<MemoryRequestOperation>(firstRequestNode));
279 auto secondRequestNode =
280 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
281 EXPECT_TRUE(is<MemoryRequestOperation>(secondRequestNode));
282 auto loadNode =
283 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(storeNode->input(0)->origin())->node();
284 EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
285 auto responseNode =
286 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(loadNode->input(2)->origin())->node();
287 EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
288}
289
290TEST(MemoryConverterTests, TestThetaLoad)
291{
292 using namespace jlm::llvm;
293 using namespace jlm::hls;
294
295 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
296
297 // Setup the function
298 std::cout << "Function Setup" << std::endl;
299 auto functionType = jlm::rvsdg::FunctionType::Create(
304 MemoryStateType::Create() },
305 { jlm::llvm::PointerType::Create(), MemoryStateType::Create() });
306
307 auto lambda = jlm::rvsdg::LambdaNode::Create(
308 rvsdgModule->Rvsdg().GetRootRegion(),
309 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
310
311 // Theta
312 auto theta = jlm::rvsdg::ThetaNode::create(lambda->subregion());
313 // Predicate
314 auto idv = theta->AddLoopVar(lambda->GetFunctionArguments()[0]);
315 auto lvs = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
316 auto lve = theta->AddLoopVar(lambda->GetFunctionArguments()[2]);
317 auto arm = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitadd_op>({ idv.pre, lvs.pre }, 32).output(0);
318 auto cmp = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitult_op>({ arm, lve.pre }, 32).output(0);
319 auto & matchNode = jlm::rvsdg::MatchOperation::CreateNode(*cmp, { { 1, 1 } }, 0, 2);
320 idv.post->divert_to(arm);
321 theta->set_predicate(matchNode.output(0));
322
323 // Load node
324 auto loadAddress = theta->AddLoopVar(lambda->GetFunctionArguments()[3]);
325 auto memoryStateArgument = theta->AddLoopVar(lambda->GetFunctionArguments()[4]);
326 auto loadOutput = LoadNonVolatileOperation::Create(
327 loadAddress.pre,
328 { memoryStateArgument.pre },
329 PointerType::Create(),
330 32);
331 loadAddress.post->divert_to(loadOutput[0]);
332 memoryStateArgument.post->divert_to(loadOutput[1]);
333
334 auto lambdaOutput = lambda->finalize({ theta->output(3), theta->output(4) });
335 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
336
337 auto lambdaRegion = lambda->subregion();
338 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
339
340 // Act
342 MemoryStateSeparation::CreateAndRun(*rvsdgModule, statisticsCollector);
343
344 // Assert
345 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
346 auto & entryMemoryStateSplitInput = lambdaRegion->argument(4)->SingleUser();
347 auto * entryMemoryStateSplitNode =
348 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(entryMemoryStateSplitInput);
349 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(entryMemoryStateSplitNode));
350 auto exitMemoryStateMergeNode =
351 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
352 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(exitMemoryStateMergeNode));
353
354 // Act
355 ThetaNodeConversion::CreateAndRun(*rvsdgModule, statisticsCollector);
356 // Simple assert as ConvertThetaNodes() is tested in separate unit tests
357 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
358 EXPECT_TRUE(jlm::rvsdg::Region::containsNodeType<LoopNode>(*lambdaRegion, true));
359
360 // Act
361 AddressQueueInsertion::CreateAndRun(*rvsdgModule, statisticsCollector);
362
363 // Simple assert as mem_queue() is tested in separate unit tests
364 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
365 EXPECT_TRUE(jlm::rvsdg::Region::containsOperation<StateGateOperation>(*lambdaRegion, true));
366 EXPECT_TRUE(
367 jlm::rvsdg::Region::containsOperation<MemoryStateSplitOperation>(*lambdaRegion, true));
368 EXPECT_TRUE(
369 jlm::rvsdg::Region::containsOperation<MemoryStateMergeOperation>(*lambdaRegion, true));
370
371 // Act
372 MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
373
374 // Assert
375 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
376
377 // Memory Converter replaces the lambda so we start from the root of the graph
378 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
379 EXPECT_EQ(region->numNodes(), 1u);
380 lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
381 lambdaRegion = lambda->subregion();
382
383 EXPECT_TRUE(jlm::rvsdg::Region::containsOperation<MemoryResponseOperation>(*lambdaRegion, true));
384 EXPECT_TRUE(jlm::rvsdg::Region::containsOperation<MemoryRequestOperation>(*lambdaRegion, true));
385
386 // Request Node
387 auto requestNode =
388 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
389 EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
390
391 // HLS_LOOP Node
392 auto loopOutput =
393 jlm::util::assertedCast<const jlm::rvsdg::StructuralOutput>(requestNode->input(0)->origin());
394 auto loopNode = jlm::util::assertedCast<const jlm::rvsdg::StructuralNode>(loopOutput->node());
395 EXPECT_NE(dynamic_cast<const LoopNode *>(loopNode), nullptr);
396 // Loop Result
397 auto & thetaResult = loopOutput->results;
398 EXPECT_EQ(thetaResult.size(), 1u);
399 // Load Node
400 auto loadNode =
401 jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaResult.first()->origin())->node();
402 EXPECT_TRUE(is<DecoupledLoadOperation>(loadNode));
403 // Loop Argument
404 auto thetaArgument =
405 jlm::util::assertedCast<const jlm::rvsdg::RegionArgument>(loadNode->input(1)->origin());
406 auto thetaInput = thetaArgument->input();
407
408 // Response Node
409 auto responseNode =
410 jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaInput->origin())->node();
411 EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
412
413 // Lambda argument
414 EXPECT_TRUE(is<jlm::rvsdg::RegionArgument>(responseNode->input(0)->origin()));
415}
416
417TEST(MemoryConverterTests, TestThetaStore)
418{
419 using namespace jlm::llvm;
420 using namespace jlm::hls;
421
422 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
423
424 // Setup the function
425 std::cout << "Function Setup" << std::endl;
426 auto functionType = jlm::rvsdg::FunctionType::Create(
432 MemoryStateType::Create() },
433 { MemoryStateType::Create() });
434
435 auto lambda = jlm::rvsdg::LambdaNode::Create(
436 rvsdgModule->Rvsdg().GetRootRegion(),
437 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
438
439 // Theta
440 auto theta = jlm::rvsdg::ThetaNode::create(lambda->subregion());
441 // Predicate
442 auto idv = theta->AddLoopVar(lambda->GetFunctionArguments()[0]);
443 auto lvs = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
444 auto lve = theta->AddLoopVar(lambda->GetFunctionArguments()[2]);
445 auto arm = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitadd_op>({ idv.pre, lvs.pre }, 32).output(0);
446 auto cmp = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitult_op>({ arm, lve.pre }, 32).output(0);
447 auto & matchNode = jlm::rvsdg::MatchOperation::CreateNode(*cmp, { { 1, 1 } }, 0, 2);
448 idv.post->divert_to(arm);
449 theta->set_predicate(matchNode.output(0));
450
451 // Store node
452 auto storeAddress = theta->AddLoopVar(lambda->GetFunctionArguments()[3]);
453 auto storeData = theta->AddLoopVar(lambda->GetFunctionArguments()[4]);
454 auto memoryStateArgument = theta->AddLoopVar(lambda->GetFunctionArguments()[5]);
455 auto storeOutput = StoreNonVolatileOperation::Create(
456 storeAddress.pre,
457 storeData.pre,
458 { memoryStateArgument.pre },
459 32);
460 memoryStateArgument.post->divert_to(storeOutput[0]);
461
462 auto lambdaOutput = lambda->finalize({ theta->output(5) });
463 jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
464
465 auto lambdaRegion = lambda->subregion();
466 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
467
468 // Act
470 MemoryStateSeparation::CreateAndRun(*rvsdgModule, statisticsCollector);
471
472 // Assert
473 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
474 auto & entryMemoryStateSplitInput = lambdaRegion->argument(5)->SingleUser();
475 auto * entryMemoryStateSplitNode =
476 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(entryMemoryStateSplitInput);
477 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(entryMemoryStateSplitNode));
478 auto exitMemoryStateMergeNode =
479 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
480 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(exitMemoryStateMergeNode));
481
482 // Act
483 ThetaNodeConversion::CreateAndRun(*rvsdgModule, statisticsCollector);
484 // Simple assert as ConvertThetaNodes() is tested in separate unit tests
485 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
486 EXPECT_TRUE(jlm::rvsdg::Region::containsNodeType<LoopNode>(*lambdaRegion, true));
487
488 // Act
489 AddressQueueInsertion::CreateAndRun(*rvsdgModule, statisticsCollector);
490
491 // Simple assert as mem_queue() is tested in separate unit tests
492 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
493 EXPECT_TRUE(
494 jlm::rvsdg::Region::containsOperation<MemoryStateSplitOperation>(*lambdaRegion, true));
495 EXPECT_TRUE(
496 jlm::rvsdg::Region::containsOperation<MemoryStateMergeOperation>(*lambdaRegion, true));
497
498 // Act
499 MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
500
501 // Assert
502 jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
503
504 // Memory Converter replaces the lambda so we start from the root of the graph
505 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
506 EXPECT_EQ(region->numNodes(), 1u);
507 lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
508 lambdaRegion = lambda->subregion();
509
510 EXPECT_TRUE(jlm::rvsdg::Region::containsOperation<MemoryRequestOperation>(*lambdaRegion, true));
511
512 // Request Node
513 auto requestNode =
514 jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
515 EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
516
517 // HLS_LOOP Node
518 auto loopOutput =
519 jlm::util::assertedCast<const jlm::rvsdg::StructuralOutput>(requestNode->input(0)->origin());
520 auto loopNode = jlm::util::assertedCast<const jlm::rvsdg::StructuralNode>(loopOutput->node());
521 EXPECT_NE(dynamic_cast<const LoopNode *>(loopNode), nullptr);
522 // Loop Result
523 auto & thetaResult = loopOutput->results;
524 EXPECT_EQ(thetaResult.size(), 1u);
525 // Load Node
526 auto storeNode =
527 jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaResult.first()->origin())->node();
528 EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
529 // NDMux Node
530 auto ndMuxNode =
531 jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(storeNode->input(2)->origin())->node();
532 EXPECT_TRUE(is<MuxOperation>(ndMuxNode));
533 // Loop Argument
534 EXPECT_TRUE(is<jlm::rvsdg::RegionArgument>(ndMuxNode->input(2)->origin()));
535}
static jlm::util::StatisticsCollector statisticsCollector
TEST(MemoryConverterTests, TestTraceArgument)
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition type.cpp:45
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > resultTypes)
static GraphExport & Create(Output &origin, std::string name)
Definition graph.cpp:62
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition lambda.cpp:141
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition control.hpp:220
static ThetaNode * create(rvsdg::Region *parent)
Definition theta.hpp:73
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
Definition view.cpp:142
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872