24 std::vector<MRRG::NodeDescriptor> uniq;
25 std::vector<MRRG::NodeDescriptor> nonWire;
29 for (
auto it = orig.begin(); it != orig.end(); it++)
32 auto snk = it->second;
33 std::vector<MRRG::NodeDescriptor> pair = {src, snk};
34 for (
auto i = 0; i < 2; i++)
36 if (std::find(uniq.begin(), uniq.end(), pair[i]) == uniq.end())
37 uniq.push_back(pair[i]);
49 for (
auto it = orig.begin(); it != orig.end(); it++)
50 invOrig.insert(std::pair<MRRG::NodeDescriptor, MRRG::NodeDescriptor> (it->second, it->first));
53 for (
auto& n : nonWire)
56 if (invOrig.count(n) != 0)
58 std::vector<MRRG::NodeDescriptor> srcs;
59 auto begin = invOrig.lower_bound(n);
60 auto end = invOrig.upper_bound(n);
61 for (
auto it =
begin; it !=
end; it++)
63 srcs.push_back(it->second);
69 s = invOrig.find(s)->second;
70 reduced.insert(std::pair<MRRG::NodeDescriptor, MRRG::NodeDescriptor> (s, n));
78 std::cout <<
"digraph ReducedMRRG {" << std::endl;
79 for(
auto it = reduced.begin(); it != reduced.end(); it = reduced.upper_bound(it->first))
82 while (i != reduced.upper_bound(it->first))
86 std::cout <<
"\"" << *src <<
"\" -> \"" << *des <<
"\";" << std::endl;
90 std::cout <<
"}\n" << std::endl;
98 std::shared_ptr<TimingGraph> tg_(
new tatum::TimingGraph());
105 clk =
tg->add_node(NodeType::SOURCE);
106 nr->set_node_name(
clk,
"CGRA_Clock");
108 std::vector<MRRG::NodeDescriptor> created;
109 for (
auto it = mrrg.begin(); it != mrrg.end(); it++)
111 auto src = it->first;
112 auto snk = it->second;
113 #define createNewOnly(n, l) \
115 if (std::find(l.begin(), l.end(), n) == l.end())\
134 std::shared_ptr<tatum::FixedDelayCalculator> dc_(
135 new tatum::FixedDelayCalculator(
143 std::shared_ptr<tatum::TimingConstraints> tc_(
144 new tatum::TimingConstraints()
147 clkDid =
tc->create_clock_domain(
"CGRA_Clock");
155 std::vector<MRRG::NodeDescriptor> drivers;
156 for (
auto it = m.begin(); it != m.end(); it++)
159 auto src = it->first;
160 auto match = std::find(drivers.begin(), drivers.end(), src);
161 if (match == drivers.end())
162 drivers.push_back(src);
164 for (
auto it = m.begin(); it != m.end(); it++)
167 auto snk = it->second;
168 auto match = std::find(drivers.begin(), drivers.end(), snk);
169 if (match != drivers.end())
170 drivers.erase(match);
174 for (
auto& d : drivers)
177 for (
auto& l : entity->ipins)
181 tc->set_constant_generator(ipin);
189 tc->set_constant_generator(n);
194 tatum::AnalyzerFactory<tatum::SetupHoldAnalysis>::make(
200 std::shared_ptr<tatum::TimingReporter> tr_(
201 new tatum::TimingReporter(
214 auto dot_writer = tatum::make_graphviz_dot_writer(*
tg, *
dc);
215 dot_writer.write_dot_file(
"/tmp/CGRAME_TatumTG.dot");
216 tr->report_unconstrained_setup(
"/tmp/CGRAME_TimingReport_UnconstrainedSetupAnalysis.rpt", *
analyzer);
220 tr->report_timing_setup(
"/tmp/CGRAME_TimingReport_SetupAnalysis.rpt", *
analyzer);
221 cgrame_msg(
"STA completed. Report dumped to: `/tmp/CGRAME_TimingReport_SetupAnalysis.rpt`");
235 const auto ET_COMB = tatum::EdgeType::PRIMITIVE_COMBINATIONAL;
236 const auto ET_INTERC = tatum::EdgeType::INTERCONNECT;
237 const auto ET_C_LAUN = tatum::EdgeType::PRIMITIVE_CLOCK_LAUNCH;
238 const auto ET_C_CAPT = tatum::EdgeType::PRIMITIVE_CLOCK_CAPTURE;
260 std::shared_ptr<TGEntity> reg(
new TGEntity);
268 size_t index = moduleName.find(
"_");
269 auto moduleBasename = moduleName.substr(0, index);
270 auto moduleSuffix = moduleName.substr(index + 1, moduleName.length());
271 auto key = moduleBasename +
"." + moduleSuffix;
272 auto kSetup = key +
".setup";
273 auto kHold = key +
".hold";
274 auto kC2q = key +
".c2q";
275 tatum::Time t_su, t_h, t_c2q;
277 throw cgrame_error(
"Timing model of register type \"" + kSetup +
"\" does not exist...");
279 throw cgrame_error(
"Timing model of register type \"" + kHold +
"\" does not exist...");
281 throw cgrame_error(
"Timing model of register type \"" + kC2q +
"\" does not exist...");
286 std::vector<tatum::NodeId> empty;
287 reg->ipins.push_back(empty);
294 for (
unsigned i = 0; i < (reduce?1:width); i++)
296 auto ipin =
tg->add_node(tatum::NodeType::IPIN);
297 auto opin =
tg->add_node(tatum::NodeType::OPIN);
300 nr->set_node_name(ipin, n_name +
".Q[" +
std::to_string(i) +
"] (" + moduleName +
")");
301 nr->set_node_name(opin, n_name +
".out[" +
std::to_string(i) +
"] (" + moduleName +
")");
302 auto ipin2opin =
tg->add_edge(ET_INTERC, ipin, opin);
303 reg->ipins[0].push_back(ipin);
304 reg->opins.push_back(opin);
305 reg->ipins2opins.push_back(ipin2opin);
306 maxComb.insert(ipin2opin, tatum::Time(0.));
307 minComb.insert(ipin2opin, tatum::Time(0.));
315 for (
unsigned i = 0; i < (reduce?1:width); i++)
318 auto ipin =
tg->add_node(tatum::NodeType::IPIN);
319 auto opin =
tg->add_node(tatum::NodeType::OPIN);
320 auto cpin =
tg->add_node(tatum::NodeType::CPIN);
321 auto src =
tg->add_node(tatum::NodeType::SOURCE);
322 auto snk =
tg->add_node(tatum::NodeType::SINK);
328 nr->set_node_name(ipin, n_name +
".D[" +
std::to_string(i) +
"] (" + moduleName +
")");
329 nr->set_node_name(opin, n_name +
".Q[" +
std::to_string(i) +
"] (" + moduleName +
")");
330 nr->set_node_name(cpin, n_name +
".clk");
331 nr->set_node_name(snk, n_name +
".D_sink[" +
std::to_string(i) +
"] (" + moduleName +
")");
332 nr->set_node_name(src, n_name +
".Q_source[" +
std::to_string(i) +
"] (" + moduleName +
")");
335 auto ipin2snk =
tg->add_edge(ET_COMB, ipin, snk);
336 auto src2opin =
tg->add_edge(ET_C_LAUN, src, opin);
337 auto cpin2snk =
tg->add_edge(ET_C_CAPT, cpin, snk);
338 auto cpin2src =
tg->add_edge(ET_COMB, cpin, src);
340 reg->ipins[0].push_back(ipin);
341 reg->opins.push_back(opin);
342 reg->cpins.push_back(cpin);
343 reg->srcs.push_back(src);
344 reg->snks.push_back(snk);
345 reg->ipins2snks.push_back(ipin2snk);
346 reg->srcs2opins.push_back(src2opin);
347 reg->cpins2snks.push_back(cpin2snk);
348 reg->cpins2srcs.push_back(cpin2src);
351 setup.insert(cpin2snk, t_su);
352 hold.insert(cpin2snk, t_h);
353 maxComb.insert(cpin2src, tatum::Time(0.));
354 minComb.insert(cpin2src, tatum::Time(0.));
355 maxComb.insert(ipin2snk, tatum::Time(0.));
356 minComb.insert(ipin2snk, tatum::Time(0.));
357 maxComb.insert(src2opin, t_c2q);
358 minComb.insert(src2opin, t_c2q);
370 std::shared_ptr<TGEntity> mux(
new TGEntity);
378 size_t index = moduleName.find(
"_");
379 auto moduleBasename = moduleName.substr(0, index);
380 auto moduleSuffix = moduleName.substr(index + 1, moduleName.length());
381 auto key = moduleBasename +
"." + moduleSuffix;
382 tatum::Time t_max, t_min;
385 throw cgrame_error(
"Timing model of multiplexor type \"" + key +
"\" does not exist...");
389 std::vector<tatum::NodeId> empty;
390 mux->ipins.push_back(empty);
393 for (
unsigned i = 0; i < (reduce?1:width); i++)
396 auto ipin =
tg->add_node(tatum::NodeType::IPIN);
397 auto opin =
tg->add_node(tatum::NodeType::OPIN);
401 nr->set_node_name(ipin, n_name +
".in0[" +
std::to_string(i) +
"] (" + moduleName +
")");
402 nr->set_node_name(opin, n_name +
".out[" +
std::to_string(i) +
"] (" + moduleName +
")");
403 auto ipin2opin =
tg->add_edge(ET_COMB, ipin, opin);
404 mux->ipins[0].push_back(ipin);
405 mux->opins.push_back(opin);
406 mux->ipins2opins.push_back(ipin2opin);
409 maxComb.insert(ipin2opin, t_max);
410 minComb.insert(ipin2opin, t_min);
420 std::vector<OpGraphOpCode> aluOps =
433 std::vector<OpGraphOpCode> memOps =
444 if (std::find(aluOps.begin(), aluOps.end(), opCode) != aluOps.end())
450 std::shared_ptr<TGEntity> fu(
new TGEntity);
458 throw cgrame_error(
"Timing model of compute unit type \"" + key +
"\" does not exist...");
461 std::vector<tatum::NodeId> ipinsA;
462 std::vector<tatum::NodeId> ipinsB;
463 fu->ipins.push_back(ipinsA);
464 fu->ipins.push_back(ipinsB);
467 std::vector<tatum::NodeId> opins;
468 for (
unsigned i = 0; i < (reduce?1:width); i++)
470 auto opin =
tg->add_node(tatum::NodeType::OPIN);
471 opins.push_back(opin);
473 nr->set_node_name(opin, n_name +
".out[" +
std::to_string(i) +
"] (" + moduleName +
")");
474 fu->opins.push_back(opin);
476 for (
unsigned i = 0; i < (reduce?1:width); i++)
478 auto ipinA =
tg->add_node(tatum::NodeType::IPIN);
479 auto ipinB =
tg->add_node(tatum::NodeType::IPIN);
482 nr->set_node_name(ipinA, n_name +
".in_a[" +
std::to_string(i) +
"] (" + moduleName +
")");
483 nr->set_node_name(ipinB, n_name +
".in_b[" +
std::to_string(i) +
"] (" + moduleName +
")");
484 fu->ipins[0].push_back(ipinA);
485 fu->ipins[1].push_back(ipinB);
486 for (
unsigned j = 0; j < (reduce?1:width); j++)
488 auto ipinA2opin =
tg->add_edge(ET_COMB, ipinA, opins[j]);
489 auto ipinB2opin =
tg->add_edge(ET_COMB, ipinB, opins[j]);
490 fu->ipins2opins.push_back(ipinA2opin);
491 fu->ipins2opins.push_back(ipinB2opin);
492 maxComb.insert(ipinA2opin, t_comb);
493 minComb.insert(ipinA2opin, t_comb);
494 maxComb.insert(ipinB2opin, t_comb);
495 minComb.insert(ipinB2opin, t_comb);
499 else if (std::find(memOps.begin(), memOps.end(), opCode) != memOps.end())
501 std::shared_ptr<TGEntity> mem(
new TGEntity);
507 key =
"memUnit." + key;
509 throw cgrame_error(
"Timing model of memory unit \"" + key +
"\" does not exist...");
513 std::vector<tatum::NodeId> empty;
514 mem->ipins.push_back(empty);
515 for (
unsigned i = 0; i < (reduce?1:width); i++)
519 auto ipin =
tg->add_node(tatum::NodeType::IPIN);
520 auto opin =
tg->add_node(tatum::NodeType::OPIN);
523 nr->set_node_name(ipin, n_name +
".addr[" +
std::to_string(i) +
"] (" + moduleName +
")");
524 nr->set_node_name(opin, n_name +
".out[" +
std::to_string(i) +
"] (" + moduleName +
")");
530 mem->ipins[0].push_back(ipin);
531 mem->opins.push_back(opin);
541 std::vector<tatum::NodeId> ipinsAddr;
542 std::vector<tatum::NodeId> ipinsData;
543 mem->ipins.push_back(ipinsAddr);
544 mem->ipins.push_back(ipinsData);
545 for (
unsigned i = 0; i < (reduce?1:width); i++)
547 auto ipinAddr =
tg->add_node(tatum::NodeType::IPIN);
548 auto opinAddr =
tg->add_node(tatum::NodeType::OPIN);
549 auto ipinData =
tg->add_node(tatum::NodeType::IPIN);
550 auto opinData =
tg->add_node(tatum::NodeType::OPIN);
551 nr->set_node_name(ipinAddr, n_name +
".addr[" +
std::to_string(i) +
"] (" + moduleName +
")");
552 nr->set_node_name(opinAddr, n_name +
".extAddr[" +
std::to_string(i) +
"] (" + moduleName +
")");
553 nr->set_node_name(ipinData, n_name +
".data[" +
std::to_string(i) +
"] (" + moduleName +
")");
554 nr->set_node_name(opinData, n_name +
".extData[" +
std::to_string(i) +
"] (" + moduleName +
")");
559 auto ipin2opinAddr =
tg->add_edge(ET_COMB, ipinAddr, opinAddr);
560 auto ipin2opinData =
tg->add_edge(ET_COMB, ipinData, opinData);
561 mem->ipins[0].push_back(ipinAddr);
562 mem->ipins[1].push_back(ipinData);
563 mem->opins.push_back(opinAddr);
564 mem->opins.push_back(opinData);
565 mem->ipins2opins.push_back(ipin2opinAddr);
566 mem->ipins2opins.push_back(ipin2opinData);
569 maxComb.insert(ipin2opinAddr, t_acc);
570 minComb.insert(ipin2opinAddr, t_acc);
571 maxComb.insert(ipin2opinData, t_acc);
572 minComb.insert(ipin2opinData, t_acc);
576 throw cgrame_error(
"Non-load/store operation mapped to a memUnit");
579 auto io = std::make_shared<TGEntity>();
585 auto ipin =
tg->add_node(tatum::NodeType::IPIN);
586 nr->set_node_name(ipin, n_name +
" output pin");
589 io->ipins.emplace_back();
590 io->ipins.at(0).push_back(ipin);
593 auto io = std::make_shared<TGEntity>();
599 auto opin =
tg->add_node(tatum::NodeType::OPIN);
600 nr->set_node_name(opin, n_name +
" input pin");
603 io->opins.push_back(opin);
606 throw cgrame_error(
"Unexpected non-routing combinational entity");
613 throw cgrame_error(
"Wire entity is not a valid timing graph node");
616 throw cgrame_error(
"MRRG node is of unspecified HW entity");
632 if (snk->
et ==
HW_COMB && tg_snk->used_input > 1)
633 throw cgrame_error(
"All ports of fanout hardware `" + snk_name +
"` are assigned");
635 in_index = tg_snk->used_input;
637 if (tg_src->width != tg_snk->width)
638 throw cgrame_error(
"Edges can't be made between entities of different data width");
640 width = tg_src->width;
642 tg_snk->used_input++;
646 for (
unsigned i = 0; i < (reduce?1:width); i++)
651 auto wire =
tg->add_edge(tatum::EdgeType::INTERCONNECT, tg_src->opins[i], tg_snk->ipins[in_index][i]);
652 maxComb.insert(wire, tatum::Time(est_RC_delay));
653 minComb.insert(wire, tatum::Time(est_RC_delay));
666 std::set<MRRG::NodeDescriptor> found_non_wires;
671 found_non_wires.insert(v);
677 return found_non_wires.find(source) != found_non_wires.end();
680 v.starting_module = s->
parent;
685 return std::move(v.found_non_wires);
692 std::vector<MRRG::NodeDescriptor> fanout_nodes;
693 std::vector<MRRG::NodeDescriptor> false_path_checklist;
698 auto fanoutCount = (overriden == -1) ? fanout_nodes.size() : overriden;
701 delay = scale * (double)fanoutCount + base;
711 auto len = tg_entity->cpins.size();
712 for (
auto i = 0; i < (reduce?1:len); i++)
714 tatum::Time t_skew = tatum::Time(0.);
715 auto clkWire =
tg->add_edge(EdgeType::INTERCONNECT,
clk, tg_entity->cpins[i]);
716 maxComb.insert(clkWire, t_skew);
717 minComb.insert(clkWire, t_skew);