8 :
Module(name, loc, size, isElastic), eb_depth(depth_), hasEnable(hasEnable_)
11 if (
isElastic ==
false) {make_and_throw<cgrame_error>([&](
auto&& s) {
12 s <<
"Elastic buffer needs to be marked as elastic ";
30 std::string enable =
hasEnable ?
"enable_" :
"";
40 vjson[
"prefix"] =
"cgrame_";
41 vjson[
"parameters"] = {};
44 vjson[
"parameters"].push_back(parameter.first);
46 vjson[
"interface"] = {};
47 vjson[
"interface"].push_back(
"CGRA_Clock");
48 vjson[
"interface"].push_back(
"CGRA_Reset");
49 vjson[
"interface"].push_back(
"CGRA_Enable");
51 for (
auto& port :
ports)
53 std::string portName = port.second->getName();
54 vjson[
"interface"].push_back(portName);
58 std::string moduleDefinition;
61 moduleDefinition += std::string(
SET_INDENT) +
"parameter ADDRESS_WIDTH = $clog2(DEPTH);\n";
62 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
63 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
64 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
65 for (
auto& port :
ports)
68 std::string portTypeString = {};
71 portTypeString =
"input";
75 portTypeString =
"output";
79 portTypeString =
"output reg";
83 portTypeString =
"inout";
85 std::string portSizeString;
86 if (!(port.second->parameter).empty())
88 std::string portParameterName = port.second->parameter;
89 portSizeString =
"[" + portParameterName +
"-1:0]";
93 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
95 std::string portName = port.second->getName();
96 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
97 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
99 moduleDefinition += std::string(
SET_INDENT) +
"wire eb_enable;\n";
101 moduleDefinition += std::string(
SET_INDENT) +
"assign eb_enable = enable;\n";
102 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_valid_upstream = data_in_valid_upstream;\n";
103 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_stop_upstream = data_in_stop_upstream;\n";
105 moduleDefinition += std::string(
SET_INDENT) +
"assign eb_enable = 'b1;\n";
107 moduleDefinition += std::string(
SET_INDENT) +
"wire fifo_full, fifo_almost_full, fifo_empty, fifo_almost_empty;\n";
108 moduleDefinition += std::string(
SET_INDENT) +
"wire [DATA_WIDTH-1:0] fifo_read_data;\n";
109 moduleDefinition += std::string(
SET_INDENT) +
"wire [ADDRESS_WIDTH:0] fifo_word_count;\n";
110 moduleDefinition += std::string(
SET_INDENT) +
"wire fifo_write_en, fifo_read_en;\n";
111 moduleDefinition += std::string(
SET_INDENT) +
"assign fifo_write_en = (data_in_valid_upstream & eb_enable) & ~fifo_full;\n";
112 moduleDefinition += std::string(
SET_INDENT) +
"assign fifo_read_en = ~fifo_empty & ~data_out_stop_downstream;\n";
113 moduleDefinition += std::string(
SET_INDENT) +
"assign data_in_stop_upstream = fifo_full;\n";
114 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out_valid_downstream = ~fifo_empty;\n";
115 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out = fifo_read_data & {DATA_WIDTH{~fifo_empty}};\n";
116 moduleDefinition += std::string(
SET_INDENT) +
"// Instantiate FIFO\n";
117 moduleDefinition += std::string(
SET_INDENT) +
"fwft_fifo FIFO\n";
118 moduleDefinition += std::string(
SET_INDENT) +
"(\n";
122 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".write_en ( fifo_write_en ),\n";
123 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".write_data ( data_in ),\n";
125 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".read_en ( fifo_read_en ),\n";
126 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".read_data ( fifo_read_data ),\n";
127 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".usedw ( fifo_word_count )\n";
128 moduleDefinition += std::string(
SET_INDENT) +
");\n";
129 moduleDefinition += std::string(
SET_INDENT) +
"defparam FIFO.width = DATA_WIDTH;\n";
130 moduleDefinition += std::string(
SET_INDENT) +
"defparam FIFO.widthad = ADDRESS_WIDTH;\n";
131 moduleDefinition += std::string(
SET_INDENT) +
"defparam FIFO.depth = DEPTH;\n";
132 vjson[
"definition"] = moduleDefinition;
144 (void)mrrg_nodes_from_op_node;
147 const std::regex in_regex(
"\\.data_in$");
151 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
152 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
153 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
159 for (
auto & mrrg_nodes_from_val_by_cycle : valNodesByCycle) {
160 if (mrrg_nodes_from_val_by_cycle.empty()) {
163 bool enableBuffer =
false;
164 for (
auto & op_val_and_nodes: mrrg_nodes_from_val_by_cycle) {
165 for (
auto & mrrg_node : op_val_and_nodes.second) {
166 auto name = mrrg_node->getHierarchyQualifiedName();
167 if (regex_search(
name, in_regex)) {
197 auto& result = *result_ptr;
199 for (
unsigned i = 0; i < II; i++)
207 result.link(data_in, buff);
208 result.link(buff, data_out);
219 :
Module(name, loc, size, isElastic), fanout(fanout_)
221 if (
isElastic ==
false) {make_and_throw<cgrame_error>([&](
auto&& s) {
222 s <<
"Elastic eager fork needs to be marked as elastic ";
227 if (
fanout <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
228 s <<
"Elastic fork doesn't support fanout of <=1. Requested fanout was " <<
fanout;
235 for (
int i = 0; i <
fanout; i++) {
250 nlohmann::json vjson;
253 vjson[
"prefix"] =
"cgrame_";
254 vjson[
"parameters"] = {};
257 vjson[
"parameters"].push_back(parameter.first);
259 vjson[
"interface"] = {};
260 vjson[
"interface"].push_back(
"CGRA_Clock");
261 vjson[
"interface"].push_back(
"CGRA_Reset");
262 vjson[
"interface"].push_back(
"CGRA_Enable");
264 for (
auto& port :
ports)
266 std::string portName = port.second->getName();
267 vjson[
"interface"].push_back(portName);
271 std::string moduleDefinition;
272 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
273 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
274 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
275 for (
auto& port :
ports)
278 std::string portTypeString = {};
281 portTypeString =
"input";
285 portTypeString =
"output";
289 portTypeString =
"output reg";
293 portTypeString =
"inout";
295 std::string portSizeString;
296 if (!(port.second->parameter).empty())
298 std::string portParameterName = port.second->parameter;
299 portSizeString =
"[" + portParameterName +
"-1:0]";
303 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
305 std::string portName = port.second->getName();
306 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
307 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
312 moduleDefinition += std::string(
SET_INDENT) +
"wire enable_condition;\n";
313 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] set_t_f;\n";
314 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] en_downstream;\n";
315 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] valid_downstream;\n";
316 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] stop_downstream;\n";
317 moduleDefinition += std::string(
SET_INDENT) +
"reg [(FANOUT-1):0] state_regs;\n";
318 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] masked_state_regs;\n";
319 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] internal_stops;\n";
320 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] muxed_condition;\n";
321 moduleDefinition += std::string(
SET_INDENT) +
"wire internal_vas;\n";
322 moduleDefinition += std::string(
SET_INDENT) +
"wire mask_valid_cond;\n";
323 moduleDefinition += std::string(
SET_INDENT) +
"wire mask_cond;\n";
327 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_condition = enable_downstream[0];\n";
328 moduleDefinition += std::string(
SET_INDENT) +
"assign en_downstream = enable_downstream[FANOUT:1];\n";
329 moduleDefinition += std::string(
SET_INDENT) +
"assign set_t_f = enable_downstream[FANOUT*2:FANOUT+1];\n";
332 moduleDefinition += std::string(
SET_INDENT) +
"assign mask_cond = !enable_condition | condition;\n";
333 moduleDefinition += std::string(
SET_INDENT) +
"assign mask_valid_cond = !enable_condition | condition_valid_upstream;\n";
334 moduleDefinition += std::string(
SET_INDENT) +
"assign condition_stop_upstream = enable_condition & |internal_stops | (|({FANOUT{mask_valid_cond}} & masked_state_regs & {FANOUT{!in_valid_upstream}}));\n";
337 moduleDefinition += std::string(
SET_INDENT) +
"assign muxed_condition = enable_condition ? set_t_f & {FANOUT{mask_cond}} & en_downstream | ~set_t_f & {FANOUT{~mask_cond}} & en_downstream : {FANOUT{1'b1}};\n";
340 moduleDefinition += std::string(
SET_INDENT) +
"assign internal_stops = (stop_downstream & masked_state_regs);\n";
341 moduleDefinition += std::string(
SET_INDENT) +
"assign internal_vas = (|internal_stops) & in_valid_upstream;\n";
342 moduleDefinition += std::string(
SET_INDENT) +
"assign masked_state_regs = state_regs & en_downstream & {FANOUT{CGRA_Enable}};\n";
345 moduleDefinition += std::string(
SET_INDENT) +
"assign in_stop_upstream = |internal_stops | (|({FANOUT{!mask_valid_cond}} & masked_state_regs & {FANOUT{in_valid_upstream}}));\n";
346 moduleDefinition += std::string(
SET_INDENT) +
"assign valid_downstream = masked_state_regs & {FANOUT{in_valid_upstream}} & muxed_condition & {FANOUT{mask_valid_cond}};\n";
349 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset) begin\n";
353 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"state_regs <= internal_stops | {FANOUT{~internal_vas}};\n";
355 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
357 for (
int i = 0; i <
fanout; i++)
359 moduleDefinition +=
"\n";
361 for (
int i = 0; i <
fanout; i++)
363 moduleDefinition +=
"\n";
365 for (
int i = 0; i <
fanout; i++)
367 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_downstream_valid_upstream = in_valid_upstream;\n";
368 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_downstream_stop_upstream = in_stop_upstream;\n";
369 vjson[
"definition"] = moduleDefinition;
381 auto& result = *result_ptr;
383 for (
unsigned i = 0; i < II; i++)
390 result.link(cond, fork);
391 result.link(in, fork);
392 result.link(fork, fork_out);
393 for (
int j = 0; j <
fanout; j++) {
395 result.link(fork_out, out);
410 (void)mrrg_nodes_from_op_node;
411 const std::vector<std::regex> required_node_regexes {
412 std::regex(
"\\.fork$"), std::regex(
"\\.in$"),
414 const std::regex out_regex(
"\\.out([0-9]+)$");
417 const std::vector<std::regex> required_op_node_regexes {
418 std::regex(
"\\.fork$"),
419 std::regex(
"\\.in$"),
420 std::regex(
"\\.condition$")
424 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
425 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
426 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
431 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
432 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
433 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
440 int false_index = -1;
443 for (
int i = 0; i < valNodesByCycle.size(); i++) {
444 std::unordered_set<int> inputs_used;
445 if (!opNodesByCycle[i].empty()) {
446 auto mrrg_nodes_from_op_per_cycle = opNodesByCycle[i];
448 int required_node_types_found = 0;
449 std::vector<OpGraphOp*> brNodes;
451 for (
const auto& op_node_and_mrrg_nodes : mrrg_nodes_from_op_per_cycle) {
452 for (
const auto& req_node_regex : required_op_node_regexes) {
453 for (
const auto& mrrg_node : op_node_and_mrrg_nodes.second) {
454 std::smatch match_results;
455 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
456 if (required_node_types_found > 2) {
457 throw cgrame_error(
"found a node that matched two required node regexes");
459 required_node_types_found++;
460 brNodes.push_back(op_node_and_mrrg_nodes.first);
466 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
467 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
468 if (required_node_types_found > 0) {
469 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
470 std::smatch match_results;
471 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, out_regex);
472 if (match_results.size() == 2) {
473 std::vector<MRRG::NodeDescriptor> vals_mapped = map.
getMappingList(val_node_and_mrrg_nodes.first);
474 std::queue<const MRRGNode*> to_visit;
476 to_visit.push(mrrg_node);
477 while (!to_visit.empty()) {
478 auto curr = to_visit.front();
480 for (
auto node : mrrg.
fanout(curr)) {
481 if (std::find(vals_mapped.begin(), vals_mapped.end(), node) != vals_mapped.end()) {
482 auto it = std::find(vals_mapped.begin(), vals_mapped.end(), node);
488 auto f_node = mrrg.
fanout(last_node)[0];
490 throw cgrame_error(
"Cannot find the connection for the val ");
492 int size_vector = og.
opNodes().size();
496 for (
int i = 0; i < size_vector; i++) {
498 if (current_node == f_node) {
503 if (op ==
nullptr)
throw cgrame_error(
"Cannot find the op ");
506 if( val_node_and_mrrg_nodes.first->getPredicateForOutput(op) ==
false){
507 false_index = stoi(match_results[1].str());
508 }
else if ( val_node_and_mrrg_nodes.first->getPredicateForOutput(op) ==
true){
509 true_index = stoi(match_results[1].str());
511 throw cgrame_error(
"Error: Must specify must specify branch " + val_node_and_mrrg_nodes.first->getName() +
" predicate value ");
513 inputs_used.insert(stoi(match_results[1].str()));
521 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
522 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
524 std::vector<bool> required_node_types_found;
525 for (
const auto& req_node_regex : required_node_regexes) {
526 required_node_types_found.push_back(
false);
527 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
528 std::smatch match_results;
529 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
530 if (required_node_types_found.back()) {
531 throw cgrame_error(
"found a node that matched two required node regexes");
533 required_node_types_found.back() =
true;
540 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
541 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
542 std::smatch match_results;
543 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, out_regex);
544 if (match_results.size() == 2) {
545 inputs_used.insert(stoi(match_results[1].str()));
553 if (inputs_used.empty()) {
557 if (inputs_used.size() != 2)
throw cgrame_error(
"Branch cannot point to more than 2 outputs");
558 if (true_index == -1 || false_index == -1)
throw cgrame_error(
"ERROR Branch: must specify the true and false predicates of the branch");
561 unsigned bit_settings = 0;
562 bit_settings |= (1U << (unsigned) 0);
563 for (
const auto& input_num : inputs_used) {
564 bit_settings |= (1U << (unsigned) input_num + 1);
565 if (true_index == input_num)
566 bit_settings |= (1U << (unsigned) input_num +
fanout + 1);
573 unsigned bit_settings = 0;
574 for (
const auto& input_num : inputs_used) {
575 bit_settings |= (1U << (unsigned) input_num + 1);
587 :
Module(name, loc, size, isElastic), fanout(fanout_), unit_fork_fanout(unit_fork_fanout_)
589 if (
isElastic ==
false) {make_and_throw<cgrame_error>([&](
auto&& s) {
590 s <<
"Elastic eager fork needs to be marked as elastic ";
595 if (
fanout <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
596 s <<
"Elastic fork doesn't support fanout of <=1. Requested fanout was " <<
fanout;
599 s <<
"Elastic fork doesn't support unit fanout of <=1. Requested unit fanout was " <<
unit_fork_fanout;
605 for (
int i = 0; i <
fanout; i++) {
619 nlohmann::json vjson;
622 vjson[
"prefix"] =
"cgrame_";
623 vjson[
"parameters"] = {};
626 vjson[
"parameters"].push_back(parameter.first);
628 vjson[
"interface"] = {};
629 vjson[
"interface"].push_back(
"CGRA_Clock");
630 vjson[
"interface"].push_back(
"CGRA_Reset");
631 vjson[
"interface"].push_back(
"CGRA_Enable");
633 for (
auto& port :
ports)
635 std::string portName = port.second->getName();
636 vjson[
"interface"].push_back(portName);
640 std::string moduleDefinition;
641 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
642 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
643 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
644 for (
auto& port :
ports)
647 std::string portTypeString = {};
650 portTypeString =
"input";
654 portTypeString =
"output";
658 portTypeString =
"output reg";
662 portTypeString =
"inout";
664 std::string portSizeString;
665 if (!(port.second->parameter).empty())
667 std::string portParameterName = port.second->parameter;
668 portSizeString =
"[" + portParameterName +
"-1:0]";
672 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
674 std::string portName = port.second->getName();
675 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
676 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
681 moduleDefinition += std::string(
SET_INDENT) +
"wire stop_upstream;";
682 moduleDefinition += std::string(
SET_INDENT) +
"elastic_eager_fork #(";
684 moduleDefinition +=
".FORK_LAYERS(" +
std::to_string(fork_layers) +
"), ";
688 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".valid_upstream(in_valid_upstream),\n";
689 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".stop_upstream(stop_upstream),\n";
692 for (
int i =
fanout-1; i > 0; i--)
693 moduleDefinition +=
"out" +
std::to_string(i) +
"_valid_downstream, ";
694 moduleDefinition +=
"out0_valid_downstream}),\n";
697 for (
int i =
fanout-1; i > 0; i--)
698 moduleDefinition +=
"out" +
std::to_string(i) +
"_stop_downstream, ";
699 moduleDefinition +=
"out0_stop_downstream}),\n";
702 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".enable_downstream(enable_downstream)\n";
703 moduleDefinition += std::string(
SET_INDENT) +
");\n";
705 moduleDefinition +=
"\n";
706 for (
int i = 0; i <
fanout; i++)
708 moduleDefinition += std::string(
SET_INDENT) +
"assign in_stop_upstream = stop_upstream;\n";
709 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_downstream_valid_upstream = in_valid_upstream;\n";
710 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_downstream_stop_upstream = in_stop_upstream;\n";
711 vjson[
"definition"] = moduleDefinition;
723 auto& result = *result_ptr;
725 for (
unsigned i = 0; i < II; i++)
730 result.link(in, fork);
731 for (
int j = 0; j <
fanout; j++) {
733 result.link(fork, out);
748 (void)mrrg_nodes_from_op_node;
749 const std::vector<std::regex> required_node_regexes {
750 std::regex(
"\\.fork$"), std::regex(
"\\.in$"),
752 const std::regex in_regex(
"\\.out([0-9]+)$");
757 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
758 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
759 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
765 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
766 std::unordered_set<int> inputs_used;
768 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
770 std::vector<bool> required_node_types_found;
771 for (
const auto& req_node_regex : required_node_regexes) {
772 required_node_types_found.push_back(
false);
773 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
774 std::smatch match_results;
775 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
776 if (required_node_types_found.back()) {
777 throw cgrame_error(
"found a node that matched two required node regexes");
779 required_node_types_found.back() =
true;
786 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
787 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
788 std::smatch match_results;
789 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
790 if (match_results.size() == 2) {
791 inputs_used.insert(stoi(match_results[1].str()));
799 if (inputs_used.empty()) {
805 unsigned bit_settings = 0;
806 for (
const auto& input_num : inputs_used) {
807 bit_settings |= (1U << (unsigned) input_num);
819 :
Module(name, loc, size, isElastic), fanin(fanin_)
822 if (
isElastic ==
false) {make_and_throw<cgrame_error>([&](
auto&& s) {
823 s <<
"Elastic eager fork needs to be marked as elastic ";
826 if (
fanin <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
827 s <<
"Elastic join doesn't support fanin of <=1. Requested fanin was " <<
fanin;
831 for (
int i = 0; i <
fanin; i++) {
850 nlohmann::json vjson;
853 vjson[
"prefix"] =
"cgrame_";
854 vjson[
"parameters"] = {};
857 vjson[
"parameters"].push_back(parameter.first);
859 vjson[
"interface"] = {};
861 for (
auto& port :
ports)
863 std::string portName = port.second->getName();
864 vjson[
"interface"].push_back(portName);
868 std::string moduleDefinition;
870 for (
auto& port :
ports)
873 std::string portTypeString = {};
876 portTypeString =
"input";
880 portTypeString =
"output";
884 portTypeString =
"output reg";
888 portTypeString =
"inout";
890 std::string portSizeString;
891 if (!(port.second->parameter).empty())
893 std::string portParameterName = port.second->parameter;
894 portSizeString =
"[" + portParameterName +
"-1:0]";
898 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
900 std::string portName = port.second->getName();
901 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
902 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
906 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANIN-1):0] valid_upstream;\n";
907 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANIN-1):0] stop_upstream;\n";
908 moduleDefinition += std::string(
SET_INDENT) +
"assign valid_upstream = {";
909 for (
int i =
fanin-1; i > 0; i--)
910 moduleDefinition +=
"in" +
std::to_string(i) +
"_valid_upstream, ";
911 moduleDefinition +=
"in0_valid_upstream};\n";
913 moduleDefinition += std::string(
SET_INDENT) +
"assign {";
914 for (
int i =
fanin-1; i > 0; i--)
915 moduleDefinition +=
"in" +
std::to_string(i) +
"_stop_upstream, ";
916 moduleDefinition +=
"in0_stop_upstream} = stop_upstream;\n";
918 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANIN-1):0] masked_valid_upstream;\n";
919 moduleDefinition += std::string(
SET_INDENT) +
"assign masked_valid_upstream = valid_upstream | (~enable);\n";
920 moduleDefinition += std::string(
SET_INDENT) +
"assign out_valid_downstream = &masked_valid_upstream;\n";
921 moduleDefinition += std::string(
SET_INDENT) +
"assign stop_upstream = {FANIN{out_stop_downstream}} | (masked_valid_upstream & {FANIN{~(out_valid_downstream)}});\n";
923 moduleDefinition +=
"\n";
924 for (
int i = 0; i <
fanin; i++)
926 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_valid_upstream = out_valid_downstream;\n";
927 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_stop_upstream = out_stop_downstream;\n";
929 vjson[
"definition"] = moduleDefinition;
942 auto& result = *result_ptr;
944 for (
unsigned i = 0; i < II; i++)
947 for (
int j = 0; j <
fanin; j++) {
950 result.link(in, out);
954 result.link(in_result, out_result);
968 (void)mrrg_nodes_from_op_node;
969 const std::vector<std::regex> required_node_regexes {
970 std::regex(
"\\.out([0-9]+)$"),
972 const std::regex in_regex(
"\\.in([0-9]+)$");
977 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
978 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
979 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
985 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
986 std::unordered_set<int> inputs_used;
988 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
990 std::vector<bool> required_node_types_found;
991 for (
const auto& req_node_regex : required_node_regexes) {
992 required_node_types_found.push_back(
false);
993 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
994 std::smatch match_results;
995 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
999 required_node_types_found.back() =
true;
1006 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
1007 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1008 std::smatch match_results;
1009 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
1010 if (match_results.size() == 2) {
1011 inputs_used.insert(stoi(match_results[1].str()));
1019 if (inputs_used.empty()) {
1024 unsigned bit_settings = 0;
1025 for (
const auto& input_num : inputs_used) {
1026 bit_settings |= (1U << (unsigned) input_num);
1039 :
Module(name, loc, size), fanout(fanout_)
1044 if (
fanout <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
1045 s <<
"Elastic diverge doesn't support fanout of <=1. Requested fanout was " <<
fanout;
1053 for (
int i = 0; i <
fanout; i++) {
1068 nlohmann::json vjson;
1071 vjson[
"prefix"] =
"cgrame_";
1072 vjson[
"parameters"] = {};
1075 vjson[
"parameters"].push_back(parameter.first);
1077 vjson[
"interface"] = {};
1078 vjson[
"interface"].push_back(
"CGRA_Clock");
1079 vjson[
"interface"].push_back(
"CGRA_Reset");
1080 vjson[
"interface"].push_back(
"CGRA_Enable");
1082 for (
auto& port :
ports)
1084 std::string portName = port.second->getName();
1085 vjson[
"interface"].push_back(portName);
1089 std::string moduleDefinition;
1092 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
1093 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
1094 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
1095 for (
auto& port :
ports)
1098 std::string portTypeString = {};
1101 portTypeString =
"input";
1105 portTypeString =
"output";
1109 portTypeString =
"output reg";
1113 portTypeString =
"inout";
1115 std::string portSizeString;
1116 if (!(port.second->parameter).empty())
1118 std::string portParameterName = port.second->parameter;
1119 portSizeString =
"[" + portParameterName +
"-1:0]";
1123 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
1125 std::string portName = port.second->getName();
1126 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
1127 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
1130 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] valid_downstream;\n";
1131 moduleDefinition += std::string(
SET_INDENT) +
"wire [(FANOUT-1):0] stop_downstream;\n";
1132 moduleDefinition += std::string(
SET_INDENT) +
"wire [DATA_WIDTH*FANOUT-1:0] data_out;\n";
1134 moduleDefinition += std::string(
SET_INDENT) +
"assign valid_downstream = {";
1135 for (
int i =
fanout-1; i > 0; i--)
1136 moduleDefinition +=
"valid_downstream" +
std::to_string(i) +
", ";
1137 moduleDefinition +=
"valid_downstream0};\n";
1138 moduleDefinition += std::string(
SET_INDENT) +
"assign stop_downstream = {";
1139 for (
int i =
fanout-1; i > 0; i--)
1140 moduleDefinition +=
"stop_downstream" +
std::to_string(i) +
", ";
1141 moduleDefinition +=
"stop_downstream0};\n";
1142 moduleDefinition += std::string(
SET_INDENT) +
"assign {";
1143 for (
int i =
fanout-1; i > 0; i--)
1145 moduleDefinition +=
"data_out0} = data_out;\n";
1146 moduleDefinition += std::string(
SET_INDENT) +
"wire [FANOUT-1:0] arbiter_request, arbiter_grant;\n";
1147 moduleDefinition += std::string(
SET_INDENT) +
"assign arbiter_request = ~stop_downstream & enable_downstream;\n";
1148 moduleDefinition += std::string(
SET_INDENT) +
"// Arbiter module, which we use to select in the case of multiple upstream modules ready\n";
1149 moduleDefinition += std::string(
SET_INDENT) +
"round_robin_arbiter #(FANOUT) arbiter\n";
1150 moduleDefinition += std::string(
SET_INDENT) +
" (\n";
1151 moduleDefinition += std::string(
SET_INDENT) +
" .clk(CGRA_Clock),\n";
1152 moduleDefinition += std::string(
SET_INDENT) +
" .reset(CGRA_Reset),\n";
1153 moduleDefinition += std::string(
SET_INDENT) +
" .req_in(arbiter_request),\n";
1154 moduleDefinition += std::string(
SET_INDENT) +
" .grant_final(arbiter_grant),\n";
1155 moduleDefinition += std::string(
SET_INDENT) +
" .memory_controller_waitrequest(~valid_upstream) // Upstream valid being low should pause the arbiter\n";
1156 moduleDefinition += std::string(
SET_INDENT) +
" );\n";
1157 moduleDefinition += std::string(
SET_INDENT) +
"assign stop_upstream = ~(|arbiter_grant);\n";
1158 moduleDefinition += std::string(
SET_INDENT) +
"assign valid_downstream = arbiter_grant & {FANOUT{valid_upstream}};\n";
1159 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out = (valid_downstream) ? {FANOUT{data_in}} : 'bx;\n";
1160 vjson[
"definition"] = moduleDefinition;
1171 return new MRRG(II);
1189 {
OpCode::PHI, {
"op_phi",
"phi", {
"phi"},
"phi_sel"}}
1194 :
Module(name, loc, size, isElastic)
1195 , mux_size(mux_size_)
1199 if (
mux_size <= 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
1200 s <<
"Multiplexer doesn't support mux_size <= 1. mux_size = " <<
mux_size;
1204 for(
int i = 0; i <
mux_size; i++) {
1222 nlohmann::json vjson;
1225 vjson[
"prefix"] =
"cgrame_";
1226 vjson[
"parameters"] = {};
1229 vjson[
"parameters"].push_back(parameter.first);
1231 vjson[
"interface"] = {};
1232 vjson[
"interface"].push_back(
"CGRA_Clock");
1233 vjson[
"interface"].push_back(
"CGRA_Reset");
1234 vjson[
"interface"].push_back(
"CGRA_Enable");
1236 for (
auto& port :
ports)
1238 std::string portName = port.second->getName();
1239 vjson[
"interface"].push_back(portName);
1243 std::string moduleDefinition;
1244 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
1245 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
1246 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
1249 for (
auto& port :
ports)
1252 std::string portTypeString = {};
1255 portTypeString =
"input";
1259 portTypeString =
"output";
1263 portTypeString =
"output reg";
1267 portTypeString =
"inout";
1269 std::string portSizeString;
1272 if (!(port.second->parameter).empty())
1274 std::string portParameterName = port.second->parameter;
1275 portSizeString =
"[" + portParameterName +
"-1:0]";
1280 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
1282 std::string portName = port.second->getName();
1284 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
1285 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
1292 moduleDefinition += std::string(
SET_INDENT) +
"always @(*) begin\n";
1296 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if(select[" + stringI +
"] && in" + stringI +
"_valid_upstream)begin\n";
1297 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
" out = in" + stringI +
";\n";
1298 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
" out_valid_downstream = in" + stringI +
"_valid_upstream;\n";
1301 moduleDefinition +=
"begin\n";
1302 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
" out_valid_downstream = 0;\n";
1304 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
1305 for (
int j = 0; j <
mux_size; ++j){
1307 moduleDefinition += std::string(
SET_INDENT) +
"assign in" + stringJ +
"_stop_upstream = out_stop_downstream & select[" + stringJ +
"] ;\n";
1309 moduleDefinition += std::string(
SET_INDENT) +
"assign select_stop_upstream = out_stop_downstream;\n";
1310 moduleDefinition += std::string(
SET_INDENT) +
"assign select_valid_upstream = out_valid_downstream;\n";
1313 vjson[
"definition"] = moduleDefinition;
1324 auto& result = *result_ptr;
1326 for(
unsigned i = 0; i < II; i++)
1329 MRRG::NodeDescriptor mux = result.insert(
MRRGNode::make_routing_function(
this,
data_size, i,
"sel_inst", 0, {
Operands::BINARY_LHS,
Operands::BINARY_RHS,
Operands::BINARY_ANY}, {
OpCode::SELECT,
OpCode::PHI}, 1)).first;
1330 result.link(mux, out);
1335 result.link(in, mux);
1349 (void)mrrg_nodes_from_op_node;
1350 const std::vector<std::regex> required_node_regexes {
1351 std::regex(
"\\.out$"),
1353 const std::regex in_regex(
"\\.in([0-9]+)$");
1355 const std::vector<std::regex> required_op_node_regexes {
1356 std::regex(
"\\.out$"),
1357 std::regex(
"\\.sel_inst"),
1363 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
1364 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
1365 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
1370 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
1371 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
1372 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
1377 int used_cycles = 0;
1379 for (
int i = 0; i < valNodesByCycle.size(); i++) {
1380 std::set<int> inputs_used;
1381 if (!opNodesByCycle[i].empty()){
1383 auto mrrg_nodes_from_op_per_cycle = opNodesByCycle[i];
1385 int required_node_types_found = 0;
1386 std::vector<OpGraphOp*> phiNodes;
1388 for (
const auto& op_node_and_mrrg_nodes : mrrg_nodes_from_op_per_cycle) {
1389 for (
const auto& req_node_regex : required_op_node_regexes) {
1390 for (
const auto& mrrg_node : op_node_and_mrrg_nodes.second) {
1391 std::smatch match_results;
1392 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
1393 if (required_node_types_found > 2) {
1394 throw cgrame_error(
"found a node that matched two required node regexes");
1396 required_node_types_found++;
1397 phiNodes.push_back(op_node_and_mrrg_nodes.first);
1404 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
1405 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
1406 if (required_node_types_found > 0) {
1407 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1408 std::smatch match_results;
1409 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
1410 if (match_results.size() == 2) {
1411 inputs_used.insert(stoi(match_results[1].str()));
1419 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
1420 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
1421 std::vector<bool> required_node_types_found;
1422 for (
const auto& req_node_regex : required_node_regexes) {
1423 required_node_types_found.push_back(
false);
1424 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1425 std::smatch match_results;
1426 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
1427 if (required_node_types_found.back()) {
1428 throw cgrame_error(
"found a node that matched two required node regexes");
1430 required_node_types_found.back() =
true;
1436 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
1437 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1438 std::smatch match_results;
1439 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
1440 if (match_results.size() == 2) {
1441 inputs_used.insert(stoi(match_results[1].str()));
1450 if (inputs_used.empty()) {
1453 }
else if (inputs_used.size() > 1 && !op) {
1454 throw cgrame_error(
"Elastic Select Mux has more than input but it is not used as an select or phi operations");
1458 unsigned bit_settings = 0;
1459 for (
const auto& input_num : inputs_used) {
1460 bit_settings |= (1U << (unsigned) input_num);
1473 :
Module(name, loc, size), fanin(fanin_)
1478 if (
fanin <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
1479 s <<
"Elastic merge doesn't support fanin of <=1. Requested fanin was " <<
fanin;
1483 for (
int i = 0; i <
fanin; i++) {
1504 nlohmann::json vjson;
1507 vjson[
"prefix"] =
"cgrame_";
1508 vjson[
"parameters"] = {};
1511 vjson[
"parameters"].push_back(parameter.first);
1513 vjson[
"interface"] = {};
1514 vjson[
"interface"].push_back(
"CGRA_Clock");
1515 vjson[
"interface"].push_back(
"CGRA_Reset");
1516 vjson[
"interface"].push_back(
"CGRA_Enable");
1518 for (
auto& port :
ports)
1520 std::string portName = port.second->getName();
1521 vjson[
"interface"].push_back(portName);
1525 std::string moduleDefinition;
1526 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
1527 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
1528 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
1529 for (
auto& port :
ports)
1532 std::string portTypeString = {};
1535 portTypeString =
"input";
1539 portTypeString =
"output";
1543 portTypeString =
"output reg";
1547 portTypeString =
"inout";
1549 std::string portSizeString;
1550 if (!(port.second->parameter).empty())
1552 std::string portParameterName = port.second->parameter;
1553 portSizeString =
"[" + portParameterName +
"-1:0]";
1557 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
1559 std::string portName = port.second->getName();
1560 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
1561 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
1565 moduleDefinition += std::string(
SET_INDENT) +
"elastic_merge #(";
1572 for (
int i =
fanin-1; i > 0; i--)
1574 moduleDefinition +=
"valid_upstream0}),\n";
1577 for (
int i =
fanin-1; i > 0; i--)
1579 moduleDefinition +=
"stop_upstream0}),\n";
1581 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".valid_downstream(valid_downstream),\n";
1582 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".stop_downstream(stop_downstream),\n";
1585 for (
int i =
fanin-1; i > 0; i--)
1587 moduleDefinition +=
"data_in0}),\n";
1591 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".enable_upstream(enable_upstream)\n";
1592 moduleDefinition += std::string(
SET_INDENT) +
");\n";
1594 vjson[
"definition"] = moduleDefinition;
1606 auto& result = *result_ptr;
1608 for (
unsigned i = 0; i < II; i++)
1613 result.link(merge, out);
1614 for (
int j = 0; j <
fanin; j++) {
1616 result.link(in, merge);
1631 (void)mrrg_nodes_from_op_node;
1632 const std::vector<std::regex> required_node_regexes {
1633 std::regex(
"\\.merge$"), std::regex(
"\\.data_out$"),
1635 const std::regex in_regex(
"\\.data_in([0-9]+)$");
1640 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
1641 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
1642 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
1647 int used_cycles = 0;
1648 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
1649 std::unordered_set<int> inputs_used;
1651 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
1653 std::vector<bool> required_node_types_found;
1654 for (
const auto& req_node_regex : required_node_regexes) {
1655 required_node_types_found.push_back(
false);
1656 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1657 std::smatch match_results;
1658 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
1659 if (required_node_types_found.back()) {
1660 throw cgrame_error(
"found a node that matched two required node regexes");
1662 required_node_types_found.back() =
true;
1669 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
1670 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
1671 std::smatch match_results;
1672 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
1673 if (match_results.size() == 2) {
1674 inputs_used.insert(stoi(match_results[1].str()));
1682 if (inputs_used.empty()) {
1687 unsigned bit_settings = 0;
1688 for (
const auto& input_num : inputs_used) {
1689 bit_settings |= (1U << (unsigned) input_num);
1703 {
OpCode::FMUL, {
"op_multiply",
"multiply", {
"0"},
"mul_sel"}},
1704 {
OpCode::FDIV, {
"op_divide",
"divide", {
"20"},
"div_sel"}},
1705 {
OpCode::SQRT, {
"op_sqrt",
"sqrt", {
"17"},
"sqrt_sel"}},
1710 :
Module(name, loc), max_latency(max_latency), supported_modes(std::move(supported_modes_))
1731 nlohmann::json vjson;
1734 vjson[
"prefix"] =
"cgrame_";
1736 vjson[
"interface"] = {};
1737 vjson[
"interface"].push_back(
"CGRA_Clock");
1738 vjson[
"interface"].push_back(
"CGRA_Reset");
1739 vjson[
"interface"].push_back(
"CGRA_Enable");
1741 for (
auto& port :
ports)
1743 std::string portName = port.second->getName();
1744 vjson[
"interface"].push_back(portName);
1748 std::string moduleDefinition;
1749 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
1750 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
1751 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
1752 for (
auto& port :
ports)
1755 std::string portTypeString = {};
1758 portTypeString =
"input";
1762 portTypeString =
"output";
1766 portTypeString =
"output reg";
1770 portTypeString =
"inout";
1772 std::string portSizeString;
1773 if (!(port.second->parameter).empty())
1775 std::string portParameterName = port.second->parameter;
1776 portSizeString =
"[" + portParameterName +
"-1:0]";
1780 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
1782 std::string portName = port.second->getName();
1783 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
1784 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
1790 moduleDefinition +=
"\n";
1791 moduleDefinition += std::string(
SET_INDENT) +
"always@(posedge CGRA_Clock) begin\n";
1796 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (opcode != curr_opcode) begin\n";
1804 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (opcode == curr_opcode) begin\n";
1805 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"curr_opcode <= opcode;\n";
1807 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if (~stop_downstream) begin\n";
1810 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (stop_downstream) begin\n";
1813 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
1814 moduleDefinition +=
"\n";
1815 moduleDefinition += std::string(
SET_INDENT) +
"always@(posedge CGRA_Clock) begin\n";
1819 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (~stop_downstream) begin\n";
1822 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (stop_downstream) begin\n";
1825 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
1826 moduleDefinition +=
"\n";
1827 moduleDefinition += std::string(
SET_INDENT) +
"always@(*) begin\n";
1829 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"valid_downstream <= 0;\n";
1853 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
1855 vjson[
"definition"] = moduleDefinition;
1876 (void)mrrg_nodes_from_val_node;
1877 const auto bits_needed = std::lround(ceil(log2(
supported_modes.size())));
1883 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
1884 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
1885 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
1890 int used_cycles = 0;
1891 for (
auto & op_and_mrrg_nodes : opNodesByCycle) {
1892 if (op_and_mrrg_nodes.empty()) {
1894 }
else if (op_and_mrrg_nodes.size() == 1) {
1897 throw cgrame_error(
"couldn't find op in supported modes list");
1917 auto& result = *result_ptr;
1919 for (
unsigned i = 0; i < II; i++)
1923 result.link(in, out);
1931 :
Module(name, loc, size), input_count(input_count_)
1967 nlohmann::json vjson;
1970 vjson[
"prefix"] =
"cgrame_";
1971 vjson[
"parameters"] = {};
1974 vjson[
"parameters"].push_back(parameter.first);
1976 vjson[
"interface"] = {};
1978 for (
auto& port :
ports)
1980 std::string portName = port.second->getName();
1981 vjson[
"interface"].push_back(portName);
1985 std::string moduleDefinition;
1986 for (
auto& port :
ports)
1989 std::string portTypeString = {};
1992 portTypeString =
"input";
1996 portTypeString =
"output";
2000 portTypeString =
"output reg";
2004 portTypeString =
"inout";
2006 std::string portSizeString;
2007 if (!(port.second->parameter).empty())
2009 std::string portParameterName = port.second->parameter;
2010 portSizeString =
"[" + portParameterName +
"-1:0]";
2014 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
2016 std::string portName = port.second->getName();
2017 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
2018 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
2022 moduleDefinition += std::string(
SET_INDENT) +
"elastic_vlu_wrapper #(";
2024 moduleDefinition +=
".INPUT_COUNT(" +
std::to_string(2) +
")) vlu_wrapper (\n";
2029 moduleDefinition +=
"data_in0}),\n";
2032 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".valid_upstream(valid_upstream),\n";
2033 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".stop_upstream(stop_upstream),\n";
2034 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".valid_downstream(valid_downstream),\n";
2035 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".stop_downstream(stop_downstream),\n";
2038 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".vlu_ready(vlu_ready),\n";
2045 moduleDefinition +=
"vlu_data_in0}),\n";
2046 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".vlu_data_out(vlu_data_out)\n";
2048 moduleDefinition += std::string(
SET_INDENT) +
");\n";
2050 vjson[
"definition"] = moduleDefinition;
2062 auto& result = *result_ptr;
2064 for (
unsigned i = 0; i < II; i++)
2069 result.link(vlu_out, out);
2073 result.link(in, vlu_in);
2088 :
Module(name, loc, size) {
2097 addSubModule(
new FuncUnit(
name +
"_ALU",
loc, supported_modes_, size, II, latency,
isElastic), 0, 0.75, 0.5, 0.25);
2111 addConnection(
name +
"_join.out_valid_downstream",
"this.out_valid_downstream",
false);
2112 addConnection(
"this.out_stop_downstream",
name +
"_join.out_stop_downstream",
false);
2120 addConnection(
name +
"_join.out_valid_downstream",
name +
"_token_inducer.data_in_valid_upstream",
false);
2121 addConnection(
name +
"_token_inducer.data_in_stop_upstream",
name +
"_join.out_stop_downstream",
false);
2137 :
Module(name, loc, size) {
2165 addConnection(
name +
"_fp_wrapper.valid_downstream",
"this.out_valid_downstream",
false);
2166 addConnection(
"this.out_stop_downstream",
name +
"_fp_wrapper.stop_downstream",
false);
2174 addConnection(
name +
"_fp_wrapper.valid_downstream",
name +
"_token_inducer.data_in_valid_upstream",
false);
2175 addConnection(
name +
"_token_inducer.data_in_stop_upstream",
name +
"_fp_wrapper.stop_downstream",
false);
2185 :
Module(name, loc, size, isElastic)
2189 if (
isElastic ==
false) {make_and_throw<cgrame_error>([&](
auto&& s) {
2190 s <<
"Elastic eager fork needs to be marked as elastic ";
2212 nlohmann::json vjson;
2215 vjson[
"prefix"] =
"cgrame_";
2216 vjson[
"parameters"] = {};
2219 vjson[
"parameters"].push_back(parameter.first);
2221 vjson[
"interface"] = {};
2222 vjson[
"interface"].push_back(
"CGRA_Clock");
2223 vjson[
"interface"].push_back(
"CGRA_Reset");
2224 vjson[
"interface"].push_back(
"CGRA_Enable");
2226 for (
auto& port :
ports)
2228 std::string portName = port.second->getName();
2229 vjson[
"interface"].push_back(portName);
2233 std::string moduleDefinition;
2234 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
2235 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
2236 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
2237 for (
auto& port :
ports)
2240 std::string portTypeString = {};
2243 portTypeString =
"input";
2247 portTypeString =
"output";
2251 portTypeString =
"output reg";
2255 portTypeString =
"inout";
2257 std::string portSizeString;
2258 if (!(port.second->parameter).empty())
2260 std::string portParameterName = port.second->parameter;
2261 portSizeString =
"[" + portParameterName +
"-1:0]";
2265 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
2267 std::string portName = port.second->getName();
2268 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
2269 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
2274 moduleDefinition += std::string(
SET_INDENT) +
"reg pass;\n\n";
2275 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset) begin\n";
2276 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if (CGRA_Reset == 'b1) begin\n";
2279 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (~data_out_stop_downstream) begin\n";
2282 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"if (counter > contexts_used) begin \n";
2284 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"end else begin\n";
2286 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"counter <= counter + 1'b1;\n";
2289 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"if (counter == 1) begin \n";
2291 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"end else begin\n";
2293 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"counter <= counter + 1'b1;\n";
2299 moduleDefinition += std::string(
SET_INDENT) +
"end\n\n";
2301 moduleDefinition += std::string(
SET_INDENT) +
"assign data_in_stop_upstream = data_out_stop_downstream;\n";
2302 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out_valid_downstream = data_in_valid_upstream | pass;\n";
2303 moduleDefinition += std::string(
SET_INDENT) +
"assign token_stop_upstream = data_in_stop_upstream;\n";
2304 moduleDefinition += std::string(
SET_INDENT) +
"assign token_valid_upstream = 'b1;\n";
2305 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out = data_in;\n";
2307 vjson[
"definition"] = moduleDefinition;
2319 auto& result = *result_ptr;
2321 for (
unsigned i = 0; i < II; i++)
2330 result.link(nodes_this_cycle(
"data_in"), nodes_this_cycle(
"data_out"));
2344 (void)mrrg_nodes_from_op_node;
2345 const std::regex in_regex(
"\\.data_in$");
2352 std::set<const MRRGNode*> mrrgnodes_mapped_to;
2355 mrrgnodes_mapped_to.insert(n);
2361 mrrgnodes_mapped_to.insert(n);
2366 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
2367 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
2368 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
2373 int used_cycles = 0;
2374 for (
const auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
2375 if (mrrg_nodes_from_val_per_cycle.empty()) {
2379 for (
const auto & op_val_and_nodes: mrrg_nodes_from_val_per_cycle) {
2380 for (
const auto & mrrg_node : op_val_and_nodes.second) {
2381 auto name = mrrg_node->getHierarchyQualifiedName();
2383 if (regex_search(
name, in_regex)) {
2385 std::set<const MRRGNode*> visited;
2386 enableToken =
isNodeInCycle(mrrg_node, mrrg_node, visited, mrrgnodes_mapped_to);
2406 visited.insert(thisNode);
2409 for (
const auto& fanoutNode : thisNode->
fanout){
2412 if (visited.find(fanoutNode) == visited.end() && mrrgnodes_mapped_to.find(fanoutNode) != mrrgnodes_mapped_to.end())
2414 if (
isNodeInCycle(originNode, fanoutNode, visited, mrrgnodes_mapped_to))
2419 else if (fanoutNode == originNode) {
2428 :
Module(name, loc, size)
2429 , numInputPorts(numInputPorts_)
2430 , numOutputPorts(numOutputPorts_)
2431 , log2Registers(log2Registers_)
2432 , eb_depth(eb_depth_)
2437 if (
log2Registers < 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
2438 s <<
"RegisterFile doesn't support less than 2 registers. log2Registers = " <<
log2Registers;
2521 nlohmann::json vjson;
2524 vjson[
"prefix"] =
"cgrame_";
2525 vjson[
"parameters"] = {};
2528 vjson[
"parameters"].push_back(parameter.first);
2530 vjson[
"interface"] = {};
2531 vjson[
"interface"].push_back(
"CGRA_Clock");
2532 vjson[
"interface"].push_back(
"CGRA_Reset");
2533 vjson[
"interface"].push_back(
"CGRA_Enable");
2534 for (
auto& port :
ports)
2536 std::string portName = port.second->getName();
2537 vjson[
"interface"].push_back(portName);
2541 std::string moduleDefinition;
2542 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
2543 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
2544 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
2545 for (
auto& port :
ports)
2548 std::string portTypeString = {};
2551 portTypeString =
"input";
2555 portTypeString =
"output";
2559 portTypeString =
"output reg";
2563 portTypeString =
"inout";
2565 std::string portSizeString;
2566 if (!(port.second->parameter).empty())
2568 std::string portParameterName = port.second->parameter;
2569 portSizeString =
"[" + portParameterName +
"-1:0]";
2573 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
2575 std::string portName = port.second->getName();
2576 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
2577 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
2581 moduleDefinition += std::string(
SET_INDENT) +
"// Setting the always blocks and inside registers\n";
2582 moduleDefinition += std::string(
SET_INDENT) +
"reg [size-1:0] register[2**log2regs-1:0];\n";
2583 moduleDefinition += std::string(
SET_INDENT) +
"always@(posedge CGRA_Clock, posedge CGRA_Reset)\n";
2587 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"for (i = 0; i < 2**log2regs; i = i+1)\n";
2601 vjson[
"definition"] = moduleDefinition;
2607 :
Module(name, loc, size)
2608 , eb_depth(eb_depth_)
2609 , num_connections(num_connections_)
2613 if(
num_connections < 2) { make_and_throw<cgrame_error>([&](
auto&& s) {
2614 s <<
"ElasticMemPort doesn't support num_connections < 2. num_connections = " <<
num_connections;
2700 :
Module(name, loc, data_size)
2701 , num_inputs(num_inputs)
2702 , num_outputs(num_outputs)
2704 bool isFull = pred_type.compare(
"full") == 0 & predExist;
2705 bool isPartial = pred_type.compare(
"partial") == 0 & predExist;
2706 if (pred_type.compare(
"full") != 0 & pred_type.compare(
"partial") != 0) {
2707 std::cout << pred_type << std::endl;
2708 throw cgrame_error(
"Predication type should be full or partial");
2711 if (type < 0 || type > 5) { make_and_throw<cgrame_error>([&](
auto&& s) {
2712 s <<
"Need to insert type of elastic crossbar " << type <<
"\n";
2713 s <<
"0: no merge and no diverge \n";
2714 s <<
"1: just merge and no diverge \n";
2715 s <<
"2: no merge and just all diverge \n";
2716 s <<
"3: no merge and just diverge for ALU \n";
2717 s <<
"4: merge and all diverge \n";
2718 s <<
"5: merge and diverge for ALU \n";
2721 if (type == 3 || type == 5) {
2723 }
else if (type == 2 || type == 4) {
2727 if (type > 1 && type < 6) {
2742 std::vector<std::string> mux_out_config_conns;
2743 mux_out_config_conns.push_back(
"out_demux" +
std::to_string(i) +
".select");
2753 if (type == 0 || type == 2 || type == 3) {
2758 }
else if (isPartial) {
2765 }
else if (type == 1 || type == 4 || type == 5)
2772 if (type == 0 || type == 2 || type == 3)
2774 else if (type == 1 || type == 4 || type == 5)
2796 addConfig(
"ForkPredicateConf", {
"fork_predicate.enable_downstream"}, contexts,
isElastic);
2845 if ( type == 0 || type == 2 || type == 3) {
2851 }
else if ( type == 1 || type == 4 || type == 5) {
2864 if (type == 0 || type == 2 || type == 3) {
2866 }
else if (type == 1 || type == 4 || type == 5) {
2886 nlohmann::json vjson;
2887 auto context_size = (
parameterlist[
"contexts"] == 1) ?
"0" :
"$clog2(contexts)-1";
2889 vjson[
"prefix"] =
"cgrame_";
2890 vjson[
"parameters"] = {};
2893 vjson[
"parameters"].push_back(parameter.first);
2895 vjson[
"interface"] = {};
2896 vjson[
"interface"].push_back(
"ConfigIn");
2897 vjson[
"interface"].push_back(
"ConfigOut");
2898 vjson[
"interface"].push_back(
"Config_Clock");
2899 vjson[
"interface"].push_back(
"Config_Reset");
2900 vjson[
"interface"].push_back(
"CGRA_Clock");
2901 vjson[
"interface"].push_back(
"CGRA_Reset");
2902 vjson[
"interface"].push_back(
"CGRA_Enable");
2904 vjson[
"interface"].push_back(
"contexts_used");
2906 vjson[
"interface"].push_back(
"select");
2907 vjson[
"interface"].push_back(
"valid");
2908 vjson[
"interface"].push_back(
"stop");
2911 std::string moduleDefinition;
2912 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
2913 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
2914 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
2915 moduleDefinition += std::string(
SET_INDENT) +
"input ConfigIn;\n";
2916 moduleDefinition += std::string(
SET_INDENT) +
"input Config_Clock;\n";
2917 moduleDefinition += std::string(
SET_INDENT) +
"input Config_Reset;\n";
2918 moduleDefinition += std::string(
SET_INDENT) +
"output ConfigOut;\n";
2919 moduleDefinition += std::string(
SET_INDENT) +
"input valid;\n";
2920 moduleDefinition += std::string(
SET_INDENT) +
"input stop;\n";
2921 moduleDefinition += std::string(
SET_INDENT) +
"output [size-1:0] select;\n";
2922 moduleDefinition += std::string(
SET_INDENT) +
"reg [size-1:0] config_reg [contexts-1:0];\n\n";
2923 moduleDefinition += std::string(
SET_INDENT) +
"reg [" + context_size +
":0] context_counter;\n";
2925 moduleDefinition += std::string(
SET_INDENT) +
"output reg [" + context_size +
":0] contexts_used;\n";
2927 moduleDefinition += std::string(
SET_INDENT) +
"reg [" + context_size +
":0] contexts_used;\n";
2929 moduleDefinition += std::string(
SET_INDENT) +
"integer i;\n\n";
2931 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge Config_Clock, posedge Config_Reset)\n";
2934 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"for (i = 0; i < contexts; i = i+1) begin\n";
2935 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"config_reg[i] <= 'd0;\n";
2940 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"for (i = 0; i < contexts; i = i+1) begin\n";
2945 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"contexts_used <= ConfigIn;\n";
2946 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= {contexts_used,config_reg[i][size-1:1]};\n";
2948 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"contexts_used <= {ConfigIn,contexts_used[" + context_size +
":1]};\n";
2949 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= {contexts_used[0],config_reg[i][size-1:1]};\n";
2954 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= {ConfigIn,config_reg[i][size-1:1]};\n";
2958 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= {config_reg[i-1][0],config_reg[i][size-1:1]};\n";
2963 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"contexts_used <= ConfigIn;\n";
2964 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= contexts_used;\n";
2966 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"contexts_used <= {ConfigIn,contexts_used[" + context_size +
":1]};\n";
2967 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= contexts_used[0];\n";
2971 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= ConfigIn;\n";
2975 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"config_reg[i] <= config_reg[i-1];\n";
2982 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
2985 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"context_counter <= 'd0;\n";
2987 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (valid && !stop) begin\n";
2988 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if(context_counter > contexts_used)\n";
2990 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"context_counter <= 'd0;\n";
2994 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"if(context_counter == contexts_used)\n";
2996 moduleDefinition += std::string(
SET_HEXA_INDENT) +
"context_counter <= 'd0;\n";
2999 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"context_counter <= context_counter + 'b1;\n";
3002 moduleDefinition += std::string(
SET_INDENT) +
"assign select = config_reg[context_counter];\n";
3004 moduleDefinition += std::string(
SET_INDENT) +
"assign select = config_reg[0];\n";
3006 moduleDefinition += std::string(
SET_INDENT) +
"assign ConfigOut = config_reg[contexts-1][0];";
3008 vjson[
"definition"] = moduleDefinition;
3019 :
Module(name, loc, size), fanout(fanout_), unit_fork_fanout(unit_fork_fanout_), impl_type(impl_type_)
3024 if (
fanout <= 1) {make_and_throw<cgrame_error>([&](
auto&& s) {
3025 s <<
"Elastic fork doesn't support fanout of <=1. Requested fanout was " <<
fanout;
3028 s <<
"Elastic fork doesn't support unit fanout of <=1. Requested unit fanout was " <<
unit_fork_fanout;
3037 for (
int i = 0; i <
fanout; i++) {
3053 nlohmann::json vjson;
3056 vjson[
"prefix"] =
"cgrame_";
3057 vjson[
"parameters"] = {};
3060 vjson[
"parameters"].push_back(parameter.first);
3062 vjson[
"interface"] = {};
3064 for (
auto& port :
ports)
3066 std::string portName = port.second->getName();
3067 vjson[
"interface"].push_back(portName);
3071 std::string moduleDefinition;
3072 for (
auto& port :
ports)
3075 std::string portTypeString = {};
3078 portTypeString =
"input";
3082 portTypeString =
"output";
3086 portTypeString =
"output reg";
3090 portTypeString =
"inout";
3092 std::string portSizeString;
3093 if (!(port.second->parameter).empty())
3095 std::string portParameterName = port.second->parameter;
3096 portSizeString =
"[" + portParameterName +
"-1:0]";
3100 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
3102 std::string portName = port.second->getName();
3103 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
3104 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
3108 moduleDefinition += std::string(
SET_INDENT) +
"elastic_lazy_fork #(";
3112 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".valid_upstream(valid_upstream),\n";
3113 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".stop_upstream(stop_upstream),\n";
3116 for (
int i =
fanout-1; i > 0; i--)
3117 moduleDefinition +=
"valid_downstream" +
std::to_string(i) +
", ";
3118 moduleDefinition +=
"valid_downstream0}),\n";
3121 for (
int i =
fanout-1; i > 0; i--)
3122 moduleDefinition +=
"stop_downstream" +
std::to_string(i) +
", ";
3123 moduleDefinition +=
"stop_downstream0}),\n";
3125 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
".enable_downstream(enable_downstream)\n";
3126 moduleDefinition += std::string(
SET_INDENT) +
");\n";
3128 moduleDefinition +=
"\n";
3129 for (
int i = 0; i <
fanout; i++)
3132 vjson[
"definition"] = moduleDefinition;
3144 auto& result = *result_ptr;
3146 for (
unsigned i = 0; i < II; i++)
3151 result.link(in, fork);
3152 for (
int j = 0; j <
fanout; j++) {
3154 result.link(fork, out);
3169 (void)mrrg_nodes_from_op_node;
3170 const std::vector<std::regex> required_node_regexes {
3171 std::regex(
"\\.fork$"), std::regex(
"\\.in$"),
3173 const std::regex in_regex(
"\\.out([0-9]+)$");
3178 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
3179 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
3180 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
3185 int used_cycles = 0;
3186 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
3187 std::unordered_set<int> inputs_used;
3189 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
3191 std::vector<bool> required_node_types_found;
3192 for (
const auto& req_node_regex : required_node_regexes) {
3193 required_node_types_found.push_back(
false);
3194 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
3195 std::smatch match_results;
3196 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
3197 if (required_node_types_found.back()) {
3198 throw cgrame_error(
"found a node that matched two required node regexes");
3200 required_node_types_found.back() =
true;
3207 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
3208 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
3209 std::smatch match_results;
3210 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
3211 if (match_results.size() == 2) {
3212 inputs_used.insert(stoi(match_results[1].str()));
3220 if (inputs_used.empty()) {
3225 unsigned bit_settings = 0;
3226 for (
const auto& input_num : inputs_used) {
3227 bit_settings |= (1U << (unsigned) input_num);