19 #include <catch2/catch.hpp>
23 Module god_module(
"top",
"");
32 GIVEN(
"an empty graph") {
35 WHEN(
"inserting 1 node") {
38 THEN(
"Size should be 1") {
39 CHECK(mg.size() == 1);
43 WHEN(
"inserting 2 nodes and linking them") {
49 mg.link(firstNode, secondNode);
51 THEN(
"first node should fan into second node and second node should fan out from first node") {
52 CHECK(mg.fanout(firstNode)[0] == secondNode);
53 CHECK(mg.fanin(secondNode)[0] == firstNode);
55 AND_THEN(
"should be able to get references for nodes") {
56 CHECK(mg.getNodeRef(firstNode).op_node_desc == &op1);
57 CHECK(mg.getNodeRef(secondNode).op_node_desc == &op2);
61 AND_WHEN(
"unlinking the two nodes") {
62 mg.unlink(firstNode, secondNode);
63 auto driverFanout = mg.fanout(firstNode);
64 auto fanoutFanin = mg.fanin(secondNode);
66 CHECK(std::find(driverFanout.begin(), driverFanout.end(), secondNode) == driverFanout.end());
67 CHECK(std::find(fanoutFanin.begin(), fanoutFanin.end(), firstNode) == fanoutFanin.end());
69 CHECK(mg.fanout(firstNode).size() == 0);
70 CHECK(mg.fanin(secondNode).size() == 0);
75 GIVEN(
"a graph with a bunch of nodes") {
100 WHEN(
"erasing 1 node (Add1)") {
102 THEN(
"no nodes should have op_desc_node of Add1") {
104 auto m1Fanout = mg.fanout(m1);
105 auto m2Fanout = mg.fanout(m2);
106 auto m4Fanin = mg.fanin(m4);
108 CHECK(std::find(m1Fanout.begin(), m1Fanout.end(), m3) == m1Fanout.end());
109 CHECK(std::find(m2Fanout.begin(), m2Fanout.end(), m3) == m2Fanout.end());
110 CHECK(std::find(m4Fanin.begin(), m4Fanin.end(), m3) == m4Fanin.end());
114 WHEN(
"erasing multiple nodes") {
119 THEN(
"no segfaults should occur") {
120 auto m3Fanin = mg.fanin(m3);
121 auto m3Fanout = mg.fanout(m3);
122 auto m6Fanin = mg.fanin(m6);
124 CHECK(!mg.contains(m2));
125 CHECK(!mg.contains(m4));
126 CHECK(mg.contains(m7));
128 CHECK(std::find(m3Fanin.begin(), m3Fanin.end(), m2) == m3Fanin.end());
129 CHECK(std::find(m3Fanout.begin(), m3Fanout.end(), m4) == m3Fanout.end());
130 CHECK(std::find(m6Fanin.begin(), m6Fanin.end(), m4) == m6Fanin.end());
131 CHECK(std::find(m6Fanin.begin(), m6Fanin.end(), m5) == m6Fanin.end());
137 GIVEN(
"a self-loop mapping") {
144 Module fillerMod(
"Mod",
"");
163 WHEN(
"transforming the mapping to a graph") {
169 GIVEN(
"a mapping with multiple branches") {
173 std::vector<MRRG::NodeDescriptor> mrrgNodes;
175 std::vector<Module> modules;
176 modules.emplace_back(
"module_1",
"");
177 modules.emplace_back(
"module_2",
"");
178 modules.emplace_back(
"module_3",
"");
181 for (
auto i = 0; i < (std::ptrdiff_t)og.opNodes().size() + (std::ptrdiff_t)og.valNodes().size(); i++) {
183 if (i < (std::ptrdiff_t)og.opNodes().size()) {
192 mrrg.
link(mrrgNodes[0], mrrgNodes[17]);
193 mrrg.
link(mrrgNodes[1], mrrgNodes[24]);
194 mrrg.
link(mrrgNodes[2], mrrgNodes[26]);
195 mrrg.
link(mrrgNodes[3], mrrgNodes[25]);
196 mrrg.
link(mrrgNodes[4], mrrgNodes[18]);
197 mrrg.
link(mrrgNodes[5], mrrgNodes[19]);
198 mrrg.
link(mrrgNodes[6], mrrgNodes[27]);
199 mrrg.
link(mrrgNodes[7], mrrgNodes[29]);
200 mrrg.
link(mrrgNodes[8], mrrgNodes[28]);
201 mrrg.
link(mrrgNodes[10], mrrgNodes[20]);
202 mrrg.
link(mrrgNodes[11], mrrgNodes[31]);
203 mrrg.
link(mrrgNodes[12], mrrgNodes[30]);
204 mrrg.
link(mrrgNodes[13], mrrgNodes[21]);
205 mrrg.
link(mrrgNodes[14], mrrgNodes[22]);
206 mrrg.
link(mrrgNodes[16], mrrgNodes[23]);
208 mrrg.
link(mrrgNodes[17], mrrgNodes[2]);
209 mrrg.
link(mrrgNodes[17], mrrgNodes[5]);
210 mrrg.
link(mrrgNodes[17], mrrgNodes[11]);
211 mrrg.
link(mrrgNodes[17], mrrgNodes[0]);
212 mrrg.
link(mrrgNodes[24], mrrgNodes[0]);
213 mrrg.
link(mrrgNodes[26], mrrgNodes[4]);
214 mrrg.
link(mrrgNodes[25], mrrgNodes[2]);
215 mrrg.
link(mrrgNodes[18], mrrgNodes[10]);
216 mrrg.
link(mrrgNodes[19], mrrgNodes[7]);
217 mrrg.
link(mrrgNodes[27], mrrgNodes[5]);
218 mrrg.
link(mrrgNodes[29], mrrgNodes[9]);
219 mrrg.
link(mrrgNodes[28], mrrgNodes[7]);
220 mrrg.
link(mrrgNodes[20], mrrgNodes[14]);
221 mrrg.
link(mrrgNodes[31], mrrgNodes[13]);
222 mrrg.
link(mrrgNodes[31], mrrgNodes[15]);
223 mrrg.
link(mrrgNodes[30], mrrgNodes[11]);
224 mrrg.
link(mrrgNodes[21], mrrgNodes[4]);
225 mrrg.
link(mrrgNodes[22], mrrgNodes[15]);
226 mrrg.
link(mrrgNodes[22], mrrgNodes[16]);
227 mrrg.
link(mrrgNodes[23], mrrgNodes[16]);
231 for (
auto & op : og.opNodes()) {
235 for (
auto & val : og.valNodes()) {
240 WHEN(
"transforming the mapping to a graph") {
247 GIVEN(
"a graph with isolated routing loops") {
252 std::vector<MRRG::NodeDescriptor> mrrgNodes;
254 std::vector<Module> modules;
255 modules.emplace_back(
"module_1",
"");
256 modules.emplace_back(
"module_2",
"");
257 modules.emplace_back(
"module_3",
"");
259 int nodesToIsolate = 7;
260 for (
size_t i = 0; i < og.opNodes().size() + og.valNodes().size() + nodesToIsolate; i++) {
262 if (i < og.opNodes().size()) {
271 mrrg.
link(mrrgNodes[0], mrrgNodes[17]);
272 mrrg.
link(mrrgNodes[1], mrrgNodes[24]);
273 mrrg.
link(mrrgNodes[2], mrrgNodes[26]);
274 mrrg.
link(mrrgNodes[3], mrrgNodes[25]);
275 mrrg.
link(mrrgNodes[4], mrrgNodes[18]);
276 mrrg.
link(mrrgNodes[5], mrrgNodes[19]);
277 mrrg.
link(mrrgNodes[6], mrrgNodes[27]);
278 mrrg.
link(mrrgNodes[7], mrrgNodes[29]);
279 mrrg.
link(mrrgNodes[8], mrrgNodes[28]);
280 mrrg.
link(mrrgNodes[10], mrrgNodes[20]);
281 mrrg.
link(mrrgNodes[11], mrrgNodes[31]);
282 mrrg.
link(mrrgNodes[12], mrrgNodes[30]);
283 mrrg.
link(mrrgNodes[13], mrrgNodes[21]);
284 mrrg.
link(mrrgNodes[14], mrrgNodes[22]);
285 mrrg.
link(mrrgNodes[16], mrrgNodes[23]);
287 mrrg.
link(mrrgNodes[17], mrrgNodes[2]);
288 mrrg.
link(mrrgNodes[17], mrrgNodes[5]);
289 mrrg.
link(mrrgNodes[17], mrrgNodes[11]);
290 mrrg.
link(mrrgNodes[17], mrrgNodes[0]);
291 mrrg.
link(mrrgNodes[24], mrrgNodes[0]);
292 mrrg.
link(mrrgNodes[26], mrrgNodes[4]);
293 mrrg.
link(mrrgNodes[25], mrrgNodes[2]);
294 mrrg.
link(mrrgNodes[18], mrrgNodes[10]);
295 mrrg.
link(mrrgNodes[19], mrrgNodes[7]);
296 mrrg.
link(mrrgNodes[27], mrrgNodes[5]);
297 mrrg.
link(mrrgNodes[29], mrrgNodes[9]);
298 mrrg.
link(mrrgNodes[28], mrrgNodes[7]);
299 mrrg.
link(mrrgNodes[20], mrrgNodes[14]);
300 mrrg.
link(mrrgNodes[31], mrrgNodes[13]);
301 mrrg.
link(mrrgNodes[31], mrrgNodes[15]);
302 mrrg.
link(mrrgNodes[30], mrrgNodes[11]);
303 mrrg.
link(mrrgNodes[21], mrrgNodes[4]);
304 mrrg.
link(mrrgNodes[22], mrrgNodes[15]);
305 mrrg.
link(mrrgNodes[22], mrrgNodes[16]);
306 mrrg.
link(mrrgNodes[23], mrrgNodes[16]);
309 mrrg.
link(mrrgNodes[32], mrrgNodes[33]);
310 mrrg.
link(mrrgNodes[33], mrrgNodes[34]);
311 mrrg.
link(mrrgNodes[34], mrrgNodes[35]);
312 mrrg.
link(mrrgNodes[35], mrrgNodes[33]);
313 mrrg.
link(mrrgNodes[36], mrrgNodes[37]);
314 mrrg.
link(mrrgNodes[37], mrrgNodes[36]);
317 for (
auto & op : og.opNodes()) {
321 for (
auto & val : og.valNodes()) {
325 for (
int i = 0; i < nodesToIsolate; i++) {
326 m.
mapMRRGNode(og.valNodes()[0], mrrgNodes[og.opNodes().size()+og.valNodes().size()+i]);
332 WHEN(
"removing isolated loops") {
335 CHECK(fixedGraph.size() == 32);
339 GIVEN(
"a graph with a diamond shape") {
342 std::vector<MRRG::NodeDescriptor> mrrgNodes;
343 Mapping m(
nullptr, 1,
nullptr);
345 WHEN(
"graph has unbalanced latencies") {
359 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
360 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
361 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
362 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
363 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
364 mrrg.
link(mrrgNodes[2], mrrgNodes[6]);
365 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
366 mrrg.
link(mrrgNodes[7], mrrgNodes[8]);
367 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
368 mrrg.
link(mrrgNodes[5], mrrgNodes[9]);
369 mrrg.
link(mrrgNodes[9], mrrgNodes[10]);
370 mrrg.
link(mrrgNodes[10], mrrgNodes[11]);
373 for (
auto & val : og.valNodes()) {
379 for (
auto & op : og.opNodes()) {
387 THEN(
"checking for unbalanced graph") {
392 WHEN(
"graph has balanced latencies") {
406 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
407 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
408 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
409 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
410 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
411 mrrg.
link(mrrgNodes[2], mrrgNodes[6]);
412 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
413 mrrg.
link(mrrgNodes[7], mrrgNodes[8]);
414 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
415 mrrg.
link(mrrgNodes[5], mrrgNodes[9]);
416 mrrg.
link(mrrgNodes[9], mrrgNodes[10]);
417 mrrg.
link(mrrgNodes[10], mrrgNodes[11]);
420 for (
auto & val : og.valNodes()) {
426 for (
auto & op : og.opNodes()) {
434 THEN(
"checking for balanced graph") {
440 GIVEN(
"a graph with a loop") {
443 std::vector<MRRG::NodeDescriptor> mrrgNodes;
444 Mapping m(
nullptr, 2,
nullptr);
446 WHEN(
"graph has unbalanced latencies") {
460 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
461 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
462 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
463 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
464 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
465 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
466 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
467 mrrg.
link(mrrgNodes[7], mrrgNodes[8]);
468 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
469 mrrg.
link(mrrgNodes[9], mrrgNodes[10]);
470 mrrg.
link(mrrgNodes[10], mrrgNodes[11]);
472 mrrg.
link(mrrgNodes[8], mrrgNodes[3]);
476 for (
auto & val : og.valNodes()) {
482 for (
auto & op : og.opNodes()) {
491 THEN(
"checking for unbalanced graph") {
496 WHEN(
"graph has balanced latencies") {
510 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
511 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
512 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
513 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
514 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
515 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
516 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
517 mrrg.
link(mrrgNodes[7], mrrgNodes[8]);
518 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
519 mrrg.
link(mrrgNodes[9], mrrgNodes[10]);
520 mrrg.
link(mrrgNodes[10], mrrgNodes[11]);
522 mrrg.
link(mrrgNodes[8], mrrgNodes[3]);
526 for (
auto & val : og.valNodes()) {
532 for (
auto & op : og.opNodes()) {
540 THEN(
"checking for balanced graph") {
548 GIVEN (
"graph with a loop that contains a diamond") {
570 std::vector<MRRG::NodeDescriptor> mrrgNodes;
571 Mapping m(
nullptr, 2,
nullptr);
574 WHEN(
"graph has unbalanced latencies") {
588 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
589 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
590 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
591 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
592 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
593 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
594 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
595 mrrg.
link(mrrgNodes[5], mrrgNodes[8]);
596 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
597 mrrg.
link(mrrgNodes[5], mrrgNodes[10]);
598 mrrg.
link(mrrgNodes[9], mrrgNodes[2]);
599 mrrg.
link(mrrgNodes[7], mrrgNodes[2]);
608 for (
auto & op : og.
opNodes()) {
615 THEN(
"checking for unbalanced graph") {
621 WHEN(
"graph has balanced latencies") {
635 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
636 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
637 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
638 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
639 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
640 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
641 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
642 mrrg.
link(mrrgNodes[5], mrrgNodes[8]);
643 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
644 mrrg.
link(mrrgNodes[5], mrrgNodes[10]);
645 mrrg.
link(mrrgNodes[9], mrrgNodes[2]);
646 mrrg.
link(mrrgNodes[7], mrrgNodes[2]);
655 for (
auto & op : og.
opNodes()) {
663 THEN(
"checking for balanced graph") {
669 GIVEN (
"a graph with a diamond that contains a loop") {
690 std::vector<MRRG::NodeDescriptor> mrrgNodes;
691 Mapping m(
nullptr, 2,
nullptr);
694 WHEN(
"graph has unbalanced latencies") {
705 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
706 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
707 mrrg.
link(mrrgNodes[2], mrrgNodes[5]);
708 mrrg.
link(mrrgNodes[1], mrrgNodes[4]);
709 mrrg.
link(mrrgNodes[4], mrrgNodes[3]);
710 mrrg.
link(mrrgNodes[3], mrrgNodes[6]);
711 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
712 mrrg.
link(mrrgNodes[5], mrrgNodes[8]);
713 mrrg.
link(mrrgNodes[8], mrrgNodes[7]);
714 mrrg.
link(mrrgNodes[7], mrrgNodes[2]);
723 for (
auto & op : og.
opNodes()) {
730 THEN(
"checking for unbalanced graph") {
744 WHEN(
"graph has balanced latencies") {
755 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
756 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
757 mrrg.
link(mrrgNodes[2], mrrgNodes[5]);
758 mrrg.
link(mrrgNodes[1], mrrgNodes[4]);
759 mrrg.
link(mrrgNodes[4], mrrgNodes[3]);
760 mrrg.
link(mrrgNodes[3], mrrgNodes[6]);
761 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
762 mrrg.
link(mrrgNodes[5], mrrgNodes[8]);
763 mrrg.
link(mrrgNodes[8], mrrgNodes[7]);
764 mrrg.
link(mrrgNodes[7], mrrgNodes[2]);
773 for (
auto & op : og.
opNodes()) {
781 THEN(
"checking for balanced graph") {
788 GIVEN(
"A cyclical graph containing a 0-latency graph") {
806 std::vector<MRRG::NodeDescriptor> mrrgNodes;
807 Mapping m(
nullptr, 2,
nullptr);
810 WHEN(
"graph has unbalanced latencies") {
822 mrrg.
link(mrrgNodes[0], mrrgNodes[1]);
823 mrrg.
link(mrrgNodes[1], mrrgNodes[2]);
824 mrrg.
link(mrrgNodes[2], mrrgNodes[3]);
825 mrrg.
link(mrrgNodes[3], mrrgNodes[4]);
826 mrrg.
link(mrrgNodes[4], mrrgNodes[5]);
827 mrrg.
link(mrrgNodes[5], mrrgNodes[6]);
828 mrrg.
link(mrrgNodes[6], mrrgNodes[7]);
829 mrrg.
link(mrrgNodes[7], mrrgNodes[8]);
830 mrrg.
link(mrrgNodes[8], mrrgNodes[9]);
831 mrrg.
link(mrrgNodes[9], mrrgNodes[0]);
832 mrrg.
link(mrrgNodes[7], mrrgNodes[2]);
835 for (
auto & op : og.
opNodes()) {
848 THEN(
"checking for unbalanced graph") {
857 struct LatencyBalanceTest {
858 bool expcted_latency_balance_result;
859 std::string mapping_description;
860 std::string mrrg_description;
861 std::string opgraph_description;
863 using MGGenRetVal = std::pair<MappingGraph,MappingGraph::ToMRRGVertexMap>;
864 std::function<MGGenRetVal(
const MRRG&,
const OpGraph&)> mapping_graph_generator;
865 std::function<
MRRG()> mrrg_generator;
866 std::function<
OpGraph()> opgraph_generator;
869 struct MGSimpleArchBuilder {
876 MapOpResult map_op(
const std::string& op_name,
XY pos) {
877 const auto fu = mg.
insert({opgraph->
getOp(op_name)}).first;
879 return { fu, pos, std::move(op_name) };
882 auto link_ops(
const MapOpResult& src,
const MapOpResult& sink,
int dest_in) {
883 const auto out = mg.
insert(src.fu, {opgraph->getVal(src.name +
"_out")}).first;
884 const auto inter = mg.
insert(out, {opgraph->
getVal(src.name +
"_out")}).first;
885 const auto in = mg.
insert(inter, {opgraph->
getVal(src.name +
"_out")}).first;
886 mg.
link(in, sink.fu);
888 toMRRG[inter] = mrrg->
getNode(0,
xyName(
"fu_out", src.pos) +
"-to-" +
xyidName(
"pe_in", sink.pos, dest_in));
891 return Result { out, inter, in };
894 LatencyBalanceTest::MGGenRetVal consume() && {
895 return {std::move(mg), std::move(toMRRG)};
899 LatencyBalanceTest::MGGenRetVal makeMG_loop_around_fu_00(
const MRRG& mrrg,
const OpGraph& og) {
900 auto builder = MGSimpleArchBuilder{&mrrg, &og};
901 const auto op_l = builder.map_op(
"op_l", {0,0});
902 builder.link_ops(op_l, op_l, 0);
903 return std::move(builder).consume();
906 LatencyBalanceTest::MGGenRetVal makeMG_reconvergence_121_00_to_11(
const MRRG& mrrg,
const OpGraph& og) {
907 auto builder = MGSimpleArchBuilder{&mrrg, &og};
908 const auto op_a = builder.map_op(
"op_a", {0,0});
909 const auto op_b = builder.map_op(
"op_b", {0,1});
910 const auto op_b2 = builder.map_op(
"op_b2", {1,0});
911 const auto op_c = builder.map_op(
"op_c", {1,1});
912 builder.link_ops(op_a, op_b, 0);
913 builder.link_ops(op_a, op_b2, 0);
914 builder.link_ops(op_b, op_c, 0);
915 builder.link_ops(op_b2, op_c, 0);
916 return std::move(builder).consume();
922 const auto test = GENERATE(values<LatencyBalanceTest>({
923 {
false,
"latency=0 cycle",
"1x1t1 ortho with self-feedback, but no FU latency",
"1 node self-loop",
924 makeMG_loop_around_fu_00,
925 []{
return makeMRRG_Simple(1, {{
"width",
"1"},{
"height",
"1"}}); },
928 {
true,
"latency=1 cycle",
"1x1t1 ortho with self-feedback, FU latency=1",
"1 node self-loop",
929 makeMG_loop_around_fu_00,
930 []{
return makeMRRG_Simple(1, {{
"width",
"1"},{
"height",
"1"},{
"fu_latency",
"1"}}); },
933 {
false,
"unbalanced re-convergence",
"2x2t1 flow ortho with self-feedback and FU latency of 1 except for FU 01",
"Converging 121",
934 makeMG_reconvergence_121_00_to_11,
935 []{
return makeMRRG_SimpleFlow(1, {{
"width",
"2"},{
"height",
"2"},{
"fu_latency",
"1"},{
xyName(
"fu_latency",{0,1}),
"0"}});},
938 {
true,
"balanced re-convergence",
"2x2t1 flow ortho with self-feedback and FU latency of 1",
"Converging 121",
939 makeMG_reconvergence_121_00_to_11,
940 []{
return makeMRRG_SimpleFlow(1, {{
"width",
"2"},{
"height",
"2"},{
"fu_latency",
"1"}});},
945 GIVEN(
"A '" << test.mrrg_description <<
"' MRRG") {
946 const auto mrrg = test.mrrg_generator();
947 GIVEN(
"A '" << test.opgraph_description <<
"' DFG") {
948 const auto opgraph = test.opgraph_generator();
949 GIVEN(
"A '" << test.mapping_description <<
"' mapping graph") {
950 const auto mg_and_tomrrg = test.mapping_graph_generator(mrrg, opgraph);
951 THEN(
"The latency check should " << (test.expcted_latency_balance_result ?
"pass" :
"fail")) {
952 const auto latency_check_result =
latencyCheck(mg_and_tomrrg.first, mrrg, mg_and_tomrrg.second);
953 CHECKED_ELSE(latency_check_result.first == test.expcted_latency_balance_result) {
954 std::cout <<
"Test Failed. Dumping inputs...";
955 std::cout <<
"\nMRRG:\n"; mrrg.
printDot(std::cout);
956 std::cout <<
"\nOpGraph:\n"; opgraph.
print_dot(std::cout);
957 std::cout <<
"\nMappingGraph:\n"; mg_and_tomrrg.first.printDot(std::cout, mrrg, opgraph, mg_and_tomrrg.second,
ConfigStore());
971 {
"fu_self_feedback",
"yes"},
972 {
"ortho_connections",
"yes"},
973 {
"diag_connections",
"no"},
974 {
"flow_conections_only",
"no"},
979 const auto inter_cluster_offsets = [&](){
980 auto result = std::vector<XY>{};
981 if (options.
getBool(
"ortho_connections")) {
982 if (not options.
getBool(
"flow_conections_only")) {
983 result.emplace_back(-1, 0);
984 result.emplace_back( 0,-1);
986 result.emplace_back( 1, 0);
987 result.emplace_back( 0, 1);
990 if (options.
getBool(
"diag_connections")) {
991 if (not options.
getBool(
"flow_conections_only")) {
992 result.emplace_back(-1,-1);
993 result.emplace_back(-1, 1);
994 result.emplace_back( 1,-1);
996 result.emplace_back( 1, 1);
999 if (options.
getBool(
"fu_self_feedback")) {
1000 result.emplace_back( 0, 0);
1006 const auto wrap_logic = [&](
XY local_xy,
XY offset) ->
XY {
1008 local_xy.first + offset.first,
1009 local_xy.second + offset.second,
1013 auto mrrg =
MRRG{II};
1018 std::vector<MRRG::NodeDescriptor> inputs;
1021 std::map<int, std::map<XY,PEData>> pe_data;
1024 for (
int ii = 0; ii < II; ++ii) {
1025 for (
int x = 0; x < options.
getInt(
"width"); ++x) {
1026 for (
int y = 0; y < options.
getInt(
"height"); ++y) {
1027 const auto xy =
XY{x,y};
1028 const auto fu_name =
xyName(
"fu", xy);
1029 const auto fu_latency = options.
getIntOr(
xyName(
"fu_latency",xy), options.
getInt(
"fu_latency"));
1030 auto& pe = pe_data[ii].insert({ xy, {
1041 mrrg.
link(pe.fu, pe.output);
1043 for (
int i = 0; i < options.
getInt(
"fu_arity"); ++i) {
1047 mrrg.
link(pe.inputs.back(), pe.fu);
1054 for (
int ii = 0; ii < II; ++ii) {
1055 for (
int x = 0; x < options.
getInt(
"width"); ++x) {
1056 for (
int y = 0; y < options.
getInt(
"height"); ++y) {
1057 const auto xy =
XY{x,y};
1058 const auto& pe = pe_data.at(ii).at(xy);
1059 for (
const auto offset : inter_cluster_offsets) {
1060 const auto remote_xy = wrap_logic(xy, offset);
1061 const auto find_results = pe_data.at(ii).find(remote_xy);
1062 if (find_results == pe_data.at(ii).end()) {
continue; }
1063 for (
const auto& remote_input : find_results->second.inputs) {
1070 mrrg.
link(pe.output, intermediate);
1071 mrrg.
link(intermediate, remote_input);
1084 {
"flow_conections_only",
"yes"}
1086 return makeMRRG_Simple(II, options);