22 {
OpCode::NOP, {
"op_nop",
"nop", {
"assign c = a;"},
"nop_sel"}},
23 {
OpCode::ADD, {
"op_add",
"add", {
"assign c = a + b ;"},
"add_sel"}},
24 {
OpCode::SUB, {
"op_sub",
"sub", {
"assign c = a - b;"},
"sub_sel"}},
25 {
OpCode::MUL, {
"op_multiply",
"multiply", {
"assign c = a * b;"},
"mul_sel"}},
26 {
OpCode::DIV, {
"op_divide",
"divide", {
"assign c = a / b;"},
"div_sel"}},
27 {
OpCode::AND, {
"op_and",
"and", {
"assign c = a & b;"},
"and_sel"}},
28 {
OpCode::OR, {
"op_or",
"or", {
"assign c = a | b;"},
"or_sel"}},
29 {
OpCode::XOR, {
"op_xor",
"xor", {
"assign c = a ^ b;"},
"xor_sel"}},
30 {
OpCode::SHL, {
"op_shl",
"shl", {
"assign c = a << b;"},
"shl_sel"}},
31 {
OpCode::LSHR, {
"op_lshr",
"lshr", {
"assign c = a >> b;"},
"lshr_sel"}},
32 {
OpCode::ASHR, {
"op_ashr",
"ashr", {
"assign c = a >>> b;"},
"ashr_sel"}},
33 {
OpCode::CONST, {
"op_const",
"const", {
"//const;"},
"const_sel"}},
34 {
OpCode::LOAD, {
"op_load",
"load", {
"//load;"},
"load_sel"}},
35 {
OpCode::STORE, {
"op_store",
"store", {
"//store;"},
"store_sel"}},
36 {
OpCode::ICMP, {
"op_cmp",
"cmp", {
"assign c = a == b? 1: 0;"},
"cmp_sel"}}
46 NameToReturn.append(
"_");
53 FuncUnit::FuncUnit(std::string name,
Location loc, std::vector<OpGraphOpCode> supported_modes_,
unsigned size,
int II,
int latency,
bool isElastic)
54 :
Module(name, loc, size, isElastic)
55 , pipeline_mode(II, latency)
56 , supported_modes(std::move(supported_modes_))
59 std::cout << II <<
'\n';
60 make_and_throw<cgrame_error>([&](
auto&& s) { s <<
"dont support an II other than 1 (given II=" << II <<
')'; });
131 throw cgrame_error(
"not enough supported modes in the list");
154 (void)mrrg_nodes_from_val_node;
155 const auto bits_needed = std::lround(ceil(log2(
supported_modes.size())));
161 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
162 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
163 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
169 for (
auto & op_and_mrrg_nodes : opNodesByCycle) {
170 if (op_and_mrrg_nodes.empty()) {
172 }
else if (op_and_mrrg_nodes.size() == 1) {
176 throw cgrame_error(
"couldn't find op in supported modes list");
198 auto& result = *result_ptr;
200 for(
unsigned i = 0; i < II; i+=
getII())
210 result.link(in_a, fu);
211 result.link(in_b, fu);
215 for(
unsigned i = 0; i < II; i+=
getII())
220 result.link(fu, out_next);
227 :
Module(name, loc, size, isElastic)
259 std::string elas =
isElastic ?
"elastic_" :
"";
265 std::cout << std::endl;
266 std::cout <<
SET_INDENT <<
"// ALERT: This module is an unimplemented place holder.\n";
272 nlohmann::json vjson;
275 vjson[
"prefix"] =
"cgrame_";
276 vjson[
"parameters"] = {};
279 vjson[
"parameters"].push_back(parameter.first);
281 vjson[
"interface"] = {};
282 for (
auto& port :
ports)
284 std::string portName = port.second->getName();
285 vjson[
"interface"].push_back(portName);
289 std::string portName = port.getName();
290 vjson[
"interface"].push_back(portName);
294 std::string moduleDefinition;
295 for (
auto& port :
ports)
298 std::string portTypeString = {};
301 portTypeString =
"input";
305 portTypeString =
"output";
309 portTypeString =
"output reg";
313 portTypeString =
"inout";
315 std::string portSizeString;
316 if (!(port.second->parameter).empty())
318 std::string portParameterName = port.second->parameter;
319 portSizeString =
"[" + portParameterName +
"-1:0]";
323 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
325 std::string portName = port.second->getName();
326 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
327 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
333 std::string portTypeString = {};
336 portTypeString =
"input";
340 portTypeString =
"output";
344 portTypeString =
"output reg";
348 portTypeString =
"inout";
350 std::string portSizeString;
351 if (!(port.parameter).empty())
353 std::string portParameterName = port.parameter;
354 portSizeString =
"[" + portParameterName +
"-1:0]";
360 std::string portName = port.getName();
361 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
362 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
367 moduleDefinition += std::string(
SET_INDENT) +
"assign addr_to_ram = addr;\n";
368 moduleDefinition += std::string(
SET_INDENT) +
"assign data_in_to_ram = data_in;\n";
370 moduleDefinition += std::string(
SET_INDENT) +
"assign w_rq_to_ram = w_rq & pred;\n";
372 moduleDefinition += std::string(
SET_INDENT) +
"assign w_rq_to_ram = w_rq;\n";
374 moduleDefinition += std::string(
SET_INDENT) +
"assign ram_input_enable = addr_valid_upstream;\n";
375 moduleDefinition += std::string(
SET_INDENT) +
"assign ram_output_ready = ~data_out_stop_downstream;\n";
376 moduleDefinition += std::string(
SET_INDENT) +
"assign addr_stop_upstream = ~ram_input_ready;\n";
377 moduleDefinition += std::string(
SET_INDENT) +
"assign data_in_stop_upstream = ~ram_input_ready;\n";
378 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out = data_out_from_ram;\n";
379 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out_valid_downstream = ram_output_enable;";
381 moduleDefinition += std::string(
SET_INDENT) +
"assign addr_to_ram = addr;\n";
382 moduleDefinition += std::string(
SET_INDENT) +
"assign data_in_to_ram = data_in;\n";
384 moduleDefinition += std::string(
SET_INDENT) +
"assign w_rq_to_ram = w_rq & pred;\n";
386 moduleDefinition += std::string(
SET_INDENT) +
"assign w_rq_to_ram = w_rq;\n";
388 moduleDefinition += std::string(
SET_INDENT) +
"assign data_out = data_out_from_ram;";
392 vjson[
"definition"] = moduleDefinition;
404 (void)mrrg_nodes_from_val_node;
405 static const std::vector<std::pair<OpGraphOpCode,std::regex>> node_name_checks {
414 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
415 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
416 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
425 if (mrrg_nodes_from_op_node_in_cycle.empty()) {
429 const OpGraphOp& op = [&]() -> decltype(
auto) {
430 if (mrrg_nodes_from_op_node_in_cycle.size() == 1) {
431 return *(
begin(mrrg_nodes_from_op_node_in_cycle)->first);
448 auto& result = *result_ptr;
450 for(
unsigned i = 0; i < II; i++)
454 {OpCode::LOAD, OpCode::STORE}
458 result.link(
pred, &fu);
463 result.link(addr, &fu);
466 result.link(data_in, &fu);
470 result.link(&fu, data_out);
481 :
Module(name, loc, size, isElastic)
488 addConnection(
"dis.out",
"this.out_valid_downstream",
false);
500 addConfig(
"ConstVal", {
"this.out"}, II,
false);
508 std::string elas =
isElastic ?
"elastic_" :
"";
517 std::cout << std::endl;
518 std::cout <<
SET_INDENT <<
"assign out = ConstVal_sig;";
519 std::cout << std::endl;
535 for (
const auto& op_and_mrrg_nodes : mrrg_nodes_from_op_node) {
536 for (
const auto& mrrg_node : op_and_mrrg_nodes.second) {
537 opNodesByCycle[mrrg_node->cycle][op_and_mrrg_nodes.first].insert(mrrg_node);
543 for (
auto & mrrg_nodes_from_op_node_per_cycle : opNodesByCycle) {
544 if (mrrg_nodes_from_op_node_per_cycle.empty()) {
547 if (mrrg_nodes_from_op_node_per_cycle.size() != 1) {
548 make_and_throw<std::logic_error>([&](
auto&& s) {
549 s <<
"This opgraph_op node is mapped to multiple MRRG nodes\n";
553 make_and_throw<std::logic_error>([&](
auto&& s) {
554 s <<
"A non constant op was mapped to this const unit\n";
559 bitConfig.
add(result, cycle);
570 auto& result = *result_ptr;
572 for(
unsigned i = 0; i < II; i++)
578 result.link(fu, data_out);
590 :
Module(name, loc, size, isElastic)
591 , numInputs(numInputs)
614 std::cout <<
"\n" <<
SET_INDENT <<
"always @*\n";
618 std::cout <<
SET_INDENT <<
"assign computation = in0;\n";
631 <<
SET_INDENT <<
"always @(posedge CGRA_Clock, posedge CGRA_Reset) begin\n"
633 <<
SET_INDENT <<
" for (i=0; i < latency; i=i+1)\n"
634 <<
SET_INDENT <<
" delay_ppln[i] <= {size{1'b0}};\n"
636 <<
SET_INDENT <<
" for (i=1; i < latency; i=i+1)\n"
637 <<
SET_INDENT <<
" delay_ppln[i] <= delay_ppln[i-1];\n"
638 <<
SET_INDENT <<
" delay_ppln[0] <= computation;\n"
644 <<
SET_INDENT <<
" assign out = delay_ppln[latency-1];\n"
646 <<
SET_INDENT <<
" assign out = computation;\n"
653 nlohmann::json vjson;
656 vjson[
"prefix"] =
"cgrame_";
657 vjson[
"parameters"] = {};
660 vjson[
"parameters"].push_back(parameter.first);
662 vjson[
"interface"] = {};
663 vjson[
"interface"].push_back(
"CGRA_Clock");
664 vjson[
"interface"].push_back(
"CGRA_Reset");
665 vjson[
"interface"].push_back(
"CGRA_Enable");
666 for (
auto& port :
ports)
668 std::string portName = port.second->getName();
669 vjson[
"interface"].push_back(portName);
673 std::string moduleDefinition;
674 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Clock;\n";
675 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Reset;\n";
676 moduleDefinition += std::string(
SET_INDENT) +
"input CGRA_Enable;\n";
677 for (
auto& port :
ports)
680 std::string portTypeString = {};
683 portTypeString =
"input";
687 portTypeString =
"output";
691 portTypeString =
"output reg";
695 portTypeString =
"inout";
697 std::string portSizeString;
698 if (!(port.second->parameter).empty())
700 std::string portParameterName = port.second->parameter;
701 portSizeString =
"[" + portParameterName +
"-1:0]";
705 portSizeString =
"[" +
std::to_string(port.second->size - 1) +
":0]";
707 std::string portName = port.second->getName();
708 std::string portDeclaration = portTypeString +
" " + portSizeString +
" " + portName +
";\n";
709 moduleDefinition += std::string(
SET_INDENT) + portDeclaration;
713 moduleDefinition += std::string(
SET_INDENT) +
"reg [size-1:0] computation;\n";
714 moduleDefinition += std::string(
SET_INDENT) +
"reg [size-1:0] delay_ppln [latency-1:0];\n";
717 moduleDefinition += std::string(
SET_INDENT) +
"always @*\n";
723 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"default: computation = {size{1'bx}};\n";
726 moduleDefinition += std::string(
SET_INDENT) +
"integer i;\n";
727 moduleDefinition += std::string(
SET_INDENT) +
"always @(posedge CGRA_Clock, posedge CGRA_Reset) begin\n";
729 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"for (i=0; i < latency; i=i+1)\n";
730 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"delay_ppln[i] <= {size{1'b0}};\n";
731 moduleDefinition += std::string(
SET_DOUBLE_INDENT) +
"end else if (CGRA_Enable) begin\n";
732 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"for (i=1; i < latency; i=i+1)\n";
733 moduleDefinition += std::string(
SET_QUAD_INDENT) +
"delay_ppln[i] <= delay_ppln[i-1];\n";
734 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"delay_ppln[0] <= computation;\n";
736 moduleDefinition += std::string(
SET_INDENT) +
"end\n\n";
738 moduleDefinition += std::string(
SET_INDENT) +
"generate\n";
740 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"assign out = delay_ppln[latency-1];\n";
742 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"assign out = computation;\n";
743 moduleDefinition += std::string(
SET_INDENT) +
"endgenerate";
746 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"assign select_valid_upstream = 1'b1;\n";
747 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"assign out_valid_downstream = 1'b1;\n";
748 moduleDefinition += std::string(
SET_TRIPLE_INDENT) +
"assign select_stop_upstream = out_stop_downstream;\n";
751 vjson[
"definition"] = moduleDefinition;