14 #include <unordered_set>
15 #include <unordered_map>
19 :
Module(name, loc, size, isElastic)
40 std::string elas =
isElastic ?
"elastic_" :
"";
47 std::cout <<
SET_INDENT <<
"always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
60 vjson[
"prefix"] =
"cgrame_";
61 vjson[
"parameters"] = {};
64 vjson[
"parameters"].push_back(parameter.first);
66 vjson[
"interface"] = {};
67 vjson[
"interface"].push_back(
"CGRA_Clock");
68 vjson[
"interface"].push_back(
"CGRA_Reset");
69 vjson[
"interface"].push_back(
"CGRA_Enable");
72 for (
auto& port :
ports)
74 std::string portName = port.second->getName();
75 vjson[
"interface"].push_back(portName);
79 std::string moduleDefinition;
80 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
81 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
82 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
83 for (
auto& port :
ports)
86 std::string portTypeString = {};
89 portTypeString =
"input";
93 portTypeString =
"output";
97 portTypeString =
"output reg";
101 portTypeString =
"inout";
103 std::string portSizeString;
104 if (!(port.second->parameter).empty())
106 std::string portParameterName = port.second->parameter;
107 portSizeString =
"[" + portParameterName +
"-1:0]";
111 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
113 std::string portName = port.second->getName();
114 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
115 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
120 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
124 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"if (enable & CGRA_Enable)\n";
128 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
129 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if (CGRA_Reset == 1) begin\n";
131 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"out_valid_downstream <= 0;\n";
133 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"else if (enable & CGRA_Enable & ~in_stop_upstream) begin\n";
135 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"out_valid_downstream <= in_valid_upstream;\n";
137 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_stop_upstream = in_stop_upstream;\n";
138 moduleDefinition += std::string(
SET_INDENT) +
"assign enable_valid_upstream = in_valid_upstream;\n";
139 moduleDefinition += std::string(
SET_INDENT) +
"assign in_stop_upstream = out_stop_downstream;\n";
142 vjson[
"definition"] = moduleDefinition;
160 const std::regex in_regex(
"\\.m_in$");
164 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
165 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
166 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
172 for (
auto & mrrg_nodes_from_val_by_cycle : valNodesByCycle) {
173 if (mrrg_nodes_from_val_by_cycle.empty()) {
176 bool enableRegister =
false;
177 for (
auto & op_val_and_nodes: mrrg_nodes_from_val_by_cycle) {
178 for (
auto & mrrg_node : op_val_and_nodes.second) {
179 auto name = mrrg_node->getHierarchyQualifiedName();
180 if (regex_search(
name, in_regex)) {
182 enableRegister =
true;
187 if (enableRegister) {
213 auto& result = *result_ptr;
216 for (
int this_cycle = 0; this_cycle < (int)II; ++this_cycle) {
226 for (
int this_cycle = 0; this_cycle < (int)II; ++this_cycle) {
227 const int next_cycle = (this_cycle + 1) % II;
232 result.link(nodes_this_cycle(
"in"), nodes_this_cycle(
"m_in"));
233 result.link(nodes_this_cycle(
"m_in"), nodes_this_cycle(
"reg"));
234 result.link(nodes_this_cycle(
"m_enable"), nodes_this_cycle(
"reg"));
235 result.link(nodes_this_cycle(
"m_out"), nodes_this_cycle(
"out"));
236 result.link(nodes_this_cycle(
"out"), nodes_this_cycle(
"m_enable"));
239 result.link(nodes_this_cycle(
"reg"), nodes_NEXT_cycle(
"m_out"));
248 :
Module(name, loc, size, isElastic), demux_size(demux_size_)
250 if (
demux_size <= 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
251 s <<
"DeMultiplexer doesn't support demux_size <= 1. demux_size = " <<
demux_size;
271 std::string elas =
isElastic ?
"elastic_" :
"";
278 nlohmann::json vjson;
281 vjson[
"prefix"] =
"cgrame_";
282 vjson[
"parameters"] = {};
285 vjson[
"parameters"].push_back(parameter.first);
287 vjson[
"interface"] = {};
288 for (
auto& port :
ports)
290 std::string portName = port.second->getName();
291 vjson[
"interface"].push_back(portName);
295 std::string moduleDefinition;
296 for (
auto& port :
ports)
299 std::string portTypeString = {};
302 portTypeString =
"input";
306 portTypeString =
"output";
310 portTypeString =
"output reg";
314 portTypeString =
"inout";
316 std::string portSizeString;
317 if (!(port.second->parameter).empty())
319 std::string portParameterName = port.second->parameter;
320 portSizeString =
"[" + portParameterName +
"-1:0]";
324 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
326 std::string portName = port.second->getName();
327 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
328 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
333 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
339 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out" + stringI +
"= in;\n";
340 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" in_stop_upstream = out" + stringI +
"_stop_downstream;\n";
344 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out" + stringJ +
"_valid_downstream = in_valid_upstream;\n";
346 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out" + stringJ +
"_valid_downstream = 1'b0;\n";
355 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
360 moduleDefinition += std::string(
SET_TRIPLE_INDENT) + stringI +
": out" + stringI +
" = in;\n";
364 vjson[
"definition"] = moduleDefinition;
376 (void)mrrg_nodes_from_op_node;
377 const std::vector<std::regex> required_node_regexes {
378 std::regex(
"\\.demux$"), std::regex(
"\\.in$"),
380 const std::regex in_regex(
"\\.out([0-9]+)$");
385 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
386 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
387 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
393 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
394 std::unordered_set<int> inputs_used;
396 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
397 std::vector<bool> required_node_types_found;
398 for (
const auto& req_node_regex : required_node_regexes) {
399 required_node_types_found.push_back(
false);
400 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
401 std::smatch match_results;
402 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
403 if (required_node_types_found.back()) {
404 throw cgrame_error(
"found a node that matched two required node regexes");
406 required_node_types_found.back() =
true;
412 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
413 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
414 std::smatch match_results;
415 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
416 if (match_results.size() == 2) {
417 inputs_used.insert(stoi(match_results[1].str()));
425 if (inputs_used.empty()) {
428 if (inputs_used.size() != 1) {
429 throw cgrame_error(
"DeMultiplexer must only have one input");
445 auto& result = *result_ptr;
447 for(
unsigned i = 0; i < II; i++)
452 result.link(in, demux);
458 result.link(demux, out);
473 :
Module(name, loc, size, isElastic)
474 , mux_size(mux_size_)
477 if (
mux_size <= 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
478 s <<
"Multiplexer doesn't support mux_size <= 1. mux_size = " <<
mux_size<<
" name "<<
name;
499 std::string elas =
isElastic ?
"elastic_" :
"";
517 nlohmann::json vjson;
520 vjson[
"prefix"] =
"cgrame_";
521 vjson[
"parameters"] = {};
524 vjson[
"parameters"].push_back(parameter.first);
526 vjson[
"interface"] = {};
527 for (
auto& port :
ports)
529 std::string portName = port.second->getName();
530 vjson[
"interface"].push_back(portName);
534 std::string moduleDefinition;
535 for (
auto& port :
ports)
538 std::string portTypeString = {};
541 portTypeString =
"input";
545 portTypeString =
"output";
549 portTypeString =
"output reg";
553 portTypeString =
"inout";
555 std::string portSizeString;
556 if (!(port.second->parameter).empty())
558 std::string portParameterName = port.second->parameter;
559 portSizeString =
"[" + portParameterName +
"-1:0]";
563 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
565 std::string portName = port.second->getName();
566 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
567 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
572 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
578 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out = in" + stringI +
";\n";
579 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out_valid_downstream = in" + stringI +
"_valid_upstream;\n";
583 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" in" + stringJ +
"_stop_upstream = out_stop_downstream;\n";
585 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" in" + stringJ +
"_stop_upstream = 1'b1;\n";
589 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"default: out = {size{1'bx}};\n";
591 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"assign select_stop_upstream = out_stop_downstream;\n";
592 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"assign select_valid_upstream = out_valid_downstream;\n";
594 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
599 moduleDefinition += std::string(
SET_TRIPLE_INDENT) + stringI +
": out = in" + stringI +
";\n";
601 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"default: out = {size{1'bx}};\n";
604 vjson[
"definition"] = moduleDefinition;
617 (void)mrrg_nodes_from_op_node;
618 const std::vector<std::regex> required_node_regexes {
619 std::regex(
"\\.mux$"), std::regex(
"\\.out$"),
621 const std::regex in_regex(
"\\.in([0-9]+)$");
626 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
627 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
628 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
634 for (
auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
635 std::unordered_set<int> inputs_used;
637 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
638 std::vector<bool> required_node_types_found;
639 for (
const auto& req_node_regex : required_node_regexes) {
640 required_node_types_found.push_back(
false);
641 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
642 std::smatch match_results;
643 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
644 if (required_node_types_found.back()) {
645 throw cgrame_error(
"found a node that matched two required node regexes");
647 required_node_types_found.back() =
true;
653 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
654 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
655 std::smatch match_results;
656 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
657 if (match_results.size() == 2) {
658 inputs_used.insert(stoi(match_results[1].str()));
666 if (inputs_used.empty()) {
669 if (inputs_used.size() != 1) {
670 throw cgrame_error(
"Multiplexer must only have one input");
685 auto& result = *result_ptr;
687 for(
unsigned i = 0; i < II; i++)
692 result.link(mux, out);
698 result.link(in, mux);
712 :
Module(name, loc, size, isElastic)
723 std::string elas =
isElastic ?
"elastic_" :
"";
730 nlohmann::json vjson;
733 vjson[
"prefix"] =
"cgrame_";
734 vjson[
"parameters"] = {};
737 vjson[
"parameters"].push_back(parameter.first);
739 vjson[
"interface"] = {};
740 for (
auto& port :
ports)
742 std::string portName = port.second->getName();
743 vjson[
"interface"].push_back(portName);
747 std::string moduleDefinition;
748 for (
auto& port :
ports)
751 std::string portTypeString = {};
754 portTypeString =
"input";
758 portTypeString =
"output";
762 portTypeString =
"output reg";
766 portTypeString =
"inout";
768 std::string portSizeString;
769 if (!(port.second->parameter).empty())
771 std::string portParameterName = port.second->parameter;
772 portSizeString =
"[" + portParameterName +
"-1:0]";
776 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
778 std::string portName = port.second->getName();
779 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
780 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
786 moduleDefinition += std::string(
SET_INDENT) +
"assign out0_valid_downstream = in_valid_upstream;\n";
787 moduleDefinition += std::string(
SET_INDENT) +
"assign in_stop_upstream = out0_stop_downstream;\n";
789 vjson[
"definition"] = moduleDefinition;
797 auto& result = *result_ptr;
799 for(
unsigned i = 0; i < II; i++)
806 result.link(truncate, out0);
807 result.link(in, truncate);
819 :
Module(name, loc, size, isElastic)
820 , numInputPorts(numInputPorts_)
821 , numOutputPorts(numOutputPorts_)
822 , log2Registers(log2Registers_)
825 if (
log2Registers < 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
826 s <<
"RegisterFile doesn't support less than 2 registers. log2Registers = " <<
log2Registers;
909 std::cout <<
"\n" <<
SET_INDENT <<
"// Setting the always blocks and inside registers\n";
910 std::cout <<
SET_INDENT <<
"reg [size-1:0] register[2**log2regs-1:0];\n";
911 std::cout <<
SET_INDENT <<
"always@(posedge CGRA_Clock, posedge CGRA_Reset)\n";
915 std::cout <<
SET_QUAD_INDENT <<
"for (i = 0; i < 2**log2regs; i = i+1)\n";
921 std::cout <<
SET_QUAD_INDENT <<
"out" << i <<
" = " <<
"register[address_out" << i <<
"];\n";
925 std::cout <<
SET_PENTA_INDENT <<
"register[address_in" << i <<
"] = in" << i <<
";\n";
933 nlohmann::json vjson;
936 vjson[
"prefix"] =
"cgrame_";
937 vjson[
"parameters"] = {};
940 vjson[
"parameters"].push_back(parameter.first);
942 vjson[
"interface"] = {};
943 vjson[
"interface"].push_back(
"CGRA_Clock");
944 vjson[
"interface"].push_back(
"CGRA_Reset");
945 vjson[
"interface"].push_back(
"CGRA_Enable");
946 for (
auto& port :
ports)
948 std::string portName = port.second->getName();
949 vjson[
"interface"].push_back(portName);
953 std::string moduleDefinition;
954 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
955 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
956 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
957 for (
auto& port :
ports)
960 std::string portTypeString = {};
963 portTypeString =
"input";
967 portTypeString =
"output";
971 portTypeString =
"output reg";
975 portTypeString =
"inout";
977 std::string portSizeString;
978 if (!(port.second->parameter).empty())
980 std::string portParameterName = port.second->parameter;
981 portSizeString =
"[" + portParameterName +
"-1:0]";
985 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
987 std::string portName = port.second->getName();
988 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
989 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
993 moduleDefinition += std::string(
SET_INDENT) +
"// Setting the always blocks and inside registers\n";
994 moduleDefinition += std::string(
SET_INDENT) +
"reg [size-1:0] register[2**log2regs-1:0];\n";
995 moduleDefinition += std::string(
SET_INDENT) +
"always@(posedge CGRA_Clock, posedge CGRA_Reset)\n";
999 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"for (i = 0; i < 2**log2regs; i = i+1)\n";
1013 vjson[
"definition"] = moduleDefinition;
1028 :
Module(name, loc, data_size)
1029 , num_inputs(num_inputs)
1030 , num_outputs(num_outputs)