17 {
OpCode::CMP, {
"op_icmp",
"cmp", {
"cmp"},
"cmp_sel"}},
46 vjson[
"prefix"] =
"cgrame_";
47 vjson[
"parameters"] = {};
51 vjson[
"parameters"].push_back(parameter.first);
53 vjson[
"interface"] = {};
56 for (
auto &port :
ports)
58 std::string portName = port.second->getName();
59 vjson[
"interface"].push_back(portName);
63 std::string moduleDefinition;
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;
101 moduleDefinition += std::string(
SET_INDENT) +
"wire pred;\n";
102 moduleDefinition += std::string(
SET_INDENT) +
"always @(*) begin\n";
103 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if (select == 3'b000) begin\n";
105 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b001) begin\n";
107 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b010) begin\n";
109 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b011) begin\n";
111 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b100) begin\n";
113 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b101) begin\n";
115 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (select == 3'b110) begin\n";
120 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
121 moduleDefinition += std::string(
SET_INDENT) +
"assign out = {pred} \n";
123 vjson[
"definition"] = moduleDefinition;
136 auto &result = *result_ptr;
138 for (
unsigned i = 0; i < II; i++)
147 result.link(in, cmp);
148 result.link(cmp, out);
167 for (
const auto &op_and_mrrg_nodes : mrrg_nodes_from_op_node)
169 for (
const auto &mrrg_node : op_and_mrrg_nodes.second)
171 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
176 for (
auto &mrrg_nodes_from_op_node_per_cycle : opNodesByCycle)
178 if (mrrg_nodes_from_op_node_per_cycle.empty())
184 if (mrrg_nodes_from_op_node_per_cycle.size() != 1)
186 make_and_throw<std::logic_error>([&](
auto &&s)
187 { s <<
"This opgraph_op node is mapped to multiple MRRG nodes\n"; });
191 make_and_throw<std::logic_error>([&](
auto &&s)
192 { s <<
"A non compare op was mapped to this compare unit\n"; });
194 std::string cmpMode =
std::begin(mrrg_nodes_from_op_node_per_cycle)->first->cmpMode;
195 std::vector<BitSetting> result;
196 if (cmpMode.compare(
"EQ") == 0)
200 else if (cmpMode.compare(
"NE") == 0)
204 else if (cmpMode.compare(
"GT") == 0)
208 else if (cmpMode.compare(
"GE") == 0)
212 else if (cmpMode.compare(
"LT") == 0)
216 else if (cmpMode.compare(
"LE") == 0)
222 make_and_throw<std::logic_error>([&](
auto &&s)
223 { s <<
"An unrecognized compare instruction mode entered\n"; });
237 {
OpCode::PHI, {
"op_phi",
"phi", {
"phi"},
"phi_sel"}}
242 :
Module(name, loc, size, isElastic)
243 , mux_size(mux_size_)
247 if (
mux_size <= 1) { make_and_throw<cgrame_error>([&](
auto&& s) {
248 s <<
"Multiplexer doesn't support mux_size <= 1. mux_size = " <<
mux_size;
274 nlohmann::json vjson;
277 vjson[
"prefix"] =
"cgrame_";
278 vjson[
"parameters"] = {};
281 vjson[
"parameters"].push_back(parameter.first);
283 vjson[
"interface"] = {};
284 vjson[
"interface"].push_back(
"CGRA_Clock");
285 vjson[
"interface"].push_back(
"CGRA_Reset");
286 vjson[
"interface"].push_back(
"CGRA_Enable");
288 for (
auto& port :
ports)
290 std::string portName = port.second->getName();
291 vjson[
"interface"].push_back(portName);
295 std::string moduleDefinition;
296 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
297 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
298 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
301 for (
auto& port :
ports)
304 std::string portTypeString = {};
307 portTypeString =
"input";
311 portTypeString =
"output";
315 portTypeString =
"output reg";
319 portTypeString =
"inout";
321 std::string portSizeString;
324 if (!(port.second->parameter).empty())
326 std::string portParameterName = port.second->parameter;
327 portSizeString =
"[" + portParameterName +
"-1:0]";
332 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
334 std::string portName = port.second->getName();
336 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
337 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
355 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
361 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out = in" + stringI +
";\n";
362 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" out_valid_downstream = in" + stringI +
"_valid_upstream;\n";
366 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" in" + stringJ +
"_stop_upstream = out_stop_downstream;\n";
368 moduleDefinition += std::string(
SET_QUAD_INDENT) +
" in" + stringJ +
"_stop_upstream = 1'b1;\n";
372 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"default: out = {size{1'bx}};\n";
374 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"assign select_stop_upstream = out_stop_downstream;\n";
375 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"assign select_valid_upstream = out_valid_downstream;\n";
377 moduleDefinition += std::string(
SET_INDENT) +
"always @(*)\n";
382 moduleDefinition += std::string(
SET_TRIPLE_INDENT) + stringI +
": out = in" + stringI +
";\n";
384 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"default: out = {size{1'bx}};\n";
388 vjson[
"definition"] = moduleDefinition;
399 auto& result = *result_ptr;
401 for(
unsigned i = 0; i < II; i++)
404 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;
407 result.link(mux, out);
408 result.link(selectpred, mux);
414 result.link(in, mux);
428 (void)mrrg_nodes_from_op_node;
429 const std::vector<std::regex> required_node_regexes {
430 std::regex(
"\\.out$"),
432 const std::regex in_regex(
"\\.in([0-9]+)$");
434 const std::vector<std::regex> required_op_node_regexes {
435 std::regex(
"\\.out$"),
436 std::regex(
"\\.sel_inst"),
442 for (
const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
443 for (
const auto& mrrg_node : val_and_mrrg_nodes.second) {
444 valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
449 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
450 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
451 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
457 for (
int i = 0; i < valNodesByCycle.size(); i++) {
458 std::set<int> inputs_used;
461 if (!opNodesByCycle[i].empty()){
462 auto mrrg_nodes_from_op_per_cycle = opNodesByCycle[i];
464 int required_node_types_found = 0;
465 std::vector<OpGraphOp*> phiNodes;
467 for (
const auto& op_node_and_mrrg_nodes : mrrg_nodes_from_op_per_cycle) {
468 for (
const auto& req_node_regex : required_op_node_regexes) {
469 for (
const auto& mrrg_node : op_node_and_mrrg_nodes.second) {
470 std::smatch match_results;
471 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
472 if (required_node_types_found > 2) {
473 throw cgrame_error(
"found a node that matched two required node regexes");
475 required_node_types_found++;
476 phiNodes.push_back(op_node_and_mrrg_nodes.first);
483 bool leftFound =
false;
484 bool rightFound =
false;
485 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
486 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
487 if (required_node_types_found > 0) {
488 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
489 std::smatch match_results;
490 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
491 if (match_results.size() == 2) {
493 if(leftFound)
throw cgrame_error(
"Error: 2 LHS inputs specfied for phi op" + phiNodes[0]->
getName());
496 left = stoi(match_results[1].str());
500 else if ( val_node_and_mrrg_nodes.first->getOperandForOutput(phiNodes[0]) ==
Operands::BINARY_RHS){
501 if(rightFound)
throw cgrame_error(
"Error: 2 RHS inputs specfied for phi op" + phiNodes[0]->
getName());
504 right = stoi(match_results[1].str());
507 }
else if ( val_node_and_mrrg_nodes.first->getOperandForOutput(phiNodes[0]) ==
Operands::PREDICATE) {
510 throw cgrame_error(
"Error: Must specify LHS/RHS for phi op " + phiNodes[0]->
getName() +
" " + val_node_and_mrrg_nodes.first->getName() +
" " + val_node_and_mrrg_nodes.first->getOperandForOutput(phiNodes[0]));
512 inputs_used.insert(stoi(match_results[1].str()));
520 auto mrrg_nodes_from_val_per_cycle = valNodesByCycle[i];
521 for (
const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
522 std::vector<bool> required_node_types_found;
523 for (
const auto& req_node_regex : required_node_regexes) {
524 required_node_types_found.push_back(
false);
525 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
526 std::smatch match_results;
527 if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
528 if (required_node_types_found.back()) {
529 throw cgrame_error(
"found a node that matched two required node regexes");
531 required_node_types_found.back() =
true;
537 if (std::all_of(
begin(required_node_types_found),
end(required_node_types_found), [&](
auto&& v) {
return v; })) {
538 for (
const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
539 std::smatch match_results;
540 std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
541 if (match_results.size() == 2) {
542 inputs_used.insert(stoi(match_results[1].str()));
551 if (inputs_used.empty()) {
553 }
else if (inputs_used.size() == 1) {
557 first_vec.insert(first_vec.end(), sec_vec.begin(), sec_vec.end() );
558 bitConfig.
add(first_vec, cycle);
559 }
else if(inputs_used.size() == 2){
562 int sec = *std::next(inputs_used.begin(), 1);
564 first_vec.insert(first_vec.end(), sec_vec.begin(), sec_vec.end());
565 bitConfig.
add(first_vec, cycle);
567 throw cgrame_error(
"ERROR: predicate MUX has to have two inputs");
581 {
OpCode::BR, {
"op_br",
"br", {
"br"},
"sel_br"}
595 auto context_size = (
parameterlist[
"contexts"] == 1) ?
"0" :
"$clog2(contexts)-1";
596 nlohmann::json vjson;
599 vjson[
"prefix"] =
"cgrame_";
600 vjson[
"parameters"] = {};
602 vjson[
"parameters"].push_back(parameter.first);
604 vjson[
"interface"] = {};
605 vjson[
"interface"].push_back(
"ConfigIn");
606 vjson[
"interface"].push_back(
"ConfigOut");
607 vjson[
"interface"].push_back(
"Config_Clock");
608 vjson[
"interface"].push_back(
"Config_Reset");
609 vjson[
"interface"].push_back(
"CGRA_Clock");
610 vjson[
"interface"].push_back(
"CGRA_Reset");
611 vjson[
"interface"].push_back(
"CGRA_Enable");
613 vjson[
"interface"].push_back(
"next_state");
614 vjson[
"interface"].push_back(
"current_state");
615 vjson[
"interface"].push_back(
"branch");
618 for (
auto& port :
ports)
620 std::string portName = port.second->getName();
621 vjson[
"interface"].push_back(portName);
625 std::string moduleDefinition;
626 for (
auto& port :
ports)
629 std::string portTypeString = {};
632 portTypeString =
"input";
636 portTypeString =
"output";
640 portTypeString =
"output reg";
644 portTypeString =
"inout";
646 std::string portSizeString;
647 if (!(port.second->parameter).empty())
649 std::string portParameterName = port.second->parameter;
650 portSizeString =
"[" + portParameterName +
"-1:0]";
654 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
656 std::string portName = port.second->getName();
657 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
658 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
661 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
662 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
663 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
665 moduleDefinition += std::string(
SET_INDENT) +
"input ConfigIn;\n";
666 moduleDefinition += std::string(
SET_INDENT) +
"input Config_Clock;\n";
667 moduleDefinition += std::string(
SET_INDENT) +
"input Config_Reset;\n";
668 moduleDefinition += std::string(
SET_INDENT) +
"output ConfigOut;\n";
669 moduleDefinition += std::string(
SET_INDENT) +
"output reg [" + context_size +
":0] next_state;\n";
670 moduleDefinition += std::string(
SET_INDENT) +
"output reg branch;\n";
671 moduleDefinition += std::string(
SET_INDENT) +
"input [" + context_size +
":0] current_state;\n";
673 moduleDefinition += std::string(
SET_INDENT) +
"reg [" + context_size +
"-1:0] event_stt_next_state [" + context_size +
"-1:0];\n";
674 moduleDefinition += std::string(
SET_INDENT) +
"reg [" + context_size +
"-1:0] event_stt_state [" + context_size +
"-1:0];\n";
675 moduleDefinition += std::string(
SET_INDENT) +
"reg event_stt_event [" + context_size +
"-1:0];\n";
676 moduleDefinition += std::string(
SET_INDENT) +
"integer i;\n";
678 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge Config_Clock) begin\n";
679 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"if (Config_Reset) begin\n";
680 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"for (i = 0; i < " + context_size +
"; i = i+1) begin\n";
681 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"event_stt_state[i] <= 0;\n";
682 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"event_stt_event[i] <= 0;\n";
683 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"event_stt_next_state[i] <= 0;\n";
687 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"for (i = 0; i < " + context_size +
"; i = i+1) begin\n";
688 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"if(i == 0) begin\n";
689 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_state[i] <= {ConfigIn,event_stt_state[i][" + context_size +
"-1:1]};\n";
690 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_event[i] <= event_stt_state[" + context_size +
"-1][0];\n";
691 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_next_state[i] <= {event_stt_event[0],event_stt_next_state[i][$clog2(" + context_size +
")-1:1]};\n";
694 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_state[i] <= {event_stt_state[i-1][0],event_stt_state[i][$clog2(" + context_size +
")-1:1]};\n";
695 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_event[i] <= event_stt_event[i-1];\n";
696 moduleDefinition += std::string(
SET_PENTA_INDENT) +
"event_stt_next_state[i] <= {event_stt_next_state[i-1][0],event_stt_next_state[i][$clog2(" + context_size +
")-1:1]};\n";
700 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
702 moduleDefinition += std::string(
SET_INDENT) +
"always @(*) begin\n";
704 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"for (i = 0; i < " + context_size +
"; i = i+1) begin\n";
705 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"if (event_stt_state[i] == current_state && event_stt_event[i] == current_event) begin\n";
706 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"next_state = event_stt_next_state[i];\n";
710 moduleDefinition += std::string(
SET_INDENT) +
"end\n";
712 moduleDefinition += std::string(
SET_INDENT) +
"assign config_out = event_stt_next_state[" + context_size +
"-1][0];\n";
714 vjson[
"definition"] = moduleDefinition;
720 return "EventTransitionTable";
726 auto& result = *result_ptr;
728 for(
unsigned i = 0; i < II; i++)
732 result.link(br, current_event);
751 for (
const auto &op_and_mrrg_nodes : mrrg_nodes_from_op_node)
753 for (
const auto &mrrg_node : op_and_mrrg_nodes.second)
755 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
760 for (
auto &mrrg_nodes_from_op_node_per_cycle : opNodesByCycle)