29 std::shared_ptr<OpGraph> opgraph,
32 int II,
bool isElastic)
40 , l_isElastic(isElastic) {
43 std::vector<std::vector<std::vector<MRRGNodeDesc>>> l_routing_nodes_3d (
l_rows, std::vector<std::vector<MRRGNodeDesc>>(
l_cols, std::vector<MRRGNodeDesc>{} ));
44 std::vector<std::vector<std::vector<MRRGNodeDesc>>> l_function_nodes_3d(
l_rows, std::vector<std::vector<MRRGNodeDesc>>(
l_cols, std::vector<MRRGNodeDesc>{}));
46 for (
const auto& mrrg_node : classes.routing_nodes[0]) {
47 uint x_loc = mrrg_node->parent->loc.x_coord;
48 uint y_loc = mrrg_node->parent->loc.y_coord;
49 if (x_loc == UINT_MAX && y_loc != UINT_MAX) {
50 for (
int i = 1; i <
l_cols - 1; i++) {
51 l_routing_nodes_3d[i][y_loc].push_back(mrrg_node);
53 }
else if (x_loc != UINT_MAX && y_loc == UINT_MAX) {
54 for (
int i = 1; i <
l_rows - 1; i++) {
55 l_routing_nodes_3d[x_loc][i].push_back(mrrg_node);
58 }
else if (x_loc != UINT_MAX && y_loc != UINT_MAX) {
59 l_routing_nodes_3d[x_loc][y_loc].push_back(mrrg_node);
61 throw cgrame_error(
"Clusterting: x & y locations are both assigned to uint max for module " + mrrg_node->parent->getName());
65 for (
const auto& mrrg_node : classes.function_nodes[0]) {
66 uint x_loc = mrrg_node->parent->loc.x_coord;
67 uint y_loc = mrrg_node->parent->loc.y_coord;
68 if (x_loc == UINT_MAX && y_loc != UINT_MAX) {
69 for (
int i = 1; i <
l_cols - 1; i++) {
70 l_function_nodes_3d[i][y_loc].push_back(mrrg_node);
72 }
else if (x_loc != UINT_MAX && y_loc == UINT_MAX) {
73 for (
int i = 1; i <
l_rows - 1; i++) {
74 l_function_nodes_3d[x_loc][i].push_back(mrrg_node);
76 }
else if (x_loc != UINT_MAX && y_loc != UINT_MAX) {
77 l_function_nodes_3d[x_loc][y_loc].push_back(mrrg_node);
79 throw cgrame_error(
"Clusterting: x & y locations are both assigned to uint max for module " + mrrg_node->parent->getName());
83 for (
int i = 0; i <
l_rows; i++) {
84 for (
int j = 0; j <
l_cols; j++) {
85 int function_node_size = l_function_nodes_3d[i][j].size();
86 int routing_node_size = l_routing_nodes_3d[i][j].size();
87 if (function_node_size == 0 && routing_node_size == 0)
continue;
90 bool same_functions =
true;
114 if (!op->getName().empty())
123 throw cgrame_error(
"Err: Memory: " + mem_name_op.first +
" has "
125 " load/store operations. That could not fit within a CGRA connected to a RAM with "
128 if (mem_name_op.second.size() ==
l_ram_ports)
continue;
130 int num_of_elements_per_port =
131 ceil(
static_cast<double>(mem_name_op.second.size())/
static_cast<double>(
l_ram_ports));
133 for (
int i = 0; i < mem_name_op.second.size(); i+= num_of_elements_per_port) {
134 std::vector<OpGraphOpDesc> ops_v;
136 std::map<int, OpGraphOp*> used_contexts;
137 for (
int j = 0; j < num_of_elements_per_port; j++) {
140 if (used_contexts.find(context) != used_contexts.end()) {
143 (
"ERR: Two memory operations that are scheduled at the same context are scheduled to be mapped together");
145 OpGraphOp* op_mem_1 = mem_name_op.second[i+j];
146 OpGraphOp* op_mem_2 = used_contexts[context];
147 std::cout <<
"Adding a new contraint " << op_mem_1->
getName() <<
" " << op_mem_2->
getName() << std::endl;
148 opPair oper_pair = {op_mem_2, op_mem_1};
154 ops_v.push_back(mem_name_op.second[i+j]);
155 visited->emplace(mem_name_op.second[i+j]);
157 used_contexts.emplace(
l_schedule[mem_name_op.second[i+j]]%
l_II, mem_name_op.second[i+j]);
167 std::set<MRRGNodeDesc> input_ports;
168 std::set<MRRGNodeDesc> output_ports;
170 for (
auto& node : *nlist) {
171 for (
auto& fanout : node->fanout) {
175 uint x_loc = node->parent->loc.x_coord;
176 uint y_loc = node->parent->loc.y_coord;
177 output_ports.emplace(node);
181 for (
auto& fanin : node->fanin) {
184 input_ports.emplace(node);
197 bool hasInput =
false;
198 for (
auto input_val : op->input) {
199 if (input_val->input && (input_val->input != op)) {
204 if (!hasInput) operations.emplace(op);
211 for (
auto& function_node : subModule.second) {
212 if (function_node->canMapOp(op)) {
213 modules_could_map_op.emplace(subModule.first, function_node);
222 std::vector<OpGraphOpDesc> ops, std::vector<MRRGNodeDesc> &used_nodes,
223 std::vector<OpGraphOpDesc> &used_ops, std::set<OpGraphOpDesc> &visited_ops, std::string submodule) {
224 std::vector<OpGraphOpDesc> next_ops;
226 for (
auto& next_op : ops) {
227 if (std::find(used_ops.begin(), used_ops.end(), next_op) != used_ops.end())
continue;
228 if (visited_ops.count(next_op) != 0)
continue;
231 if (std::find(used_nodes.begin(), used_nodes.end(), function_node) != used_nodes.end())
continue;
232 if (!function_node->canMapOp(next_op))
continue;
235 used_nodes.push_back(function_node);
236 used_ops.push_back(next_op);
241 if (next_ops.empty())
return;
249 for (
auto& sink_op : val->
output) {
250 if (std::find(ops.begin(), ops.end(), sink_op) == ops.end()) {
258 for (
auto& in_val : source_op->
input) {
260 if (std::find(ops.begin(), ops.end(), connected_op) == ops.end()) {
269 op_mrrg_nodes.clear();
272 if (function_node->canMapOp(op)) {
273 op_mrrg_nodes.push_back(function_node);
279 std::vector<MRRGNodeDesc>& op_mrrg_nodes, std::string submodule) {
281 for (
auto& op_node : op_mrrg_nodes) {
284 if (output_node->bitwidth < op_node->bitwidth)
continue;
286 bool reached_output_port =
isReachable(op_node, output_node, submodule);
288 if (reached_output_port) {
289 connected_nodes[op_node].emplace(output_node);
297 std::vector<MRRGNodeDesc>& op_mrrg_nodes, std::string submodule) {
299 for (
auto& op_mrrg_node : op_mrrg_nodes) {
301 bool reached_input_port =
isReachable(input_node, op_mrrg_node, submodule);
302 if (reached_input_port) {
303 connected_nodes[op_mrrg_node].emplace(input_node);
311 std::set<MRRGNodeDesc> ports_used,
312 std::set<OpGraphOpDesc> out_port_found,
313 std::map<
OpGraphOpDesc, std::set<MRRGNodeDesc>>& op_to_port_nodes,
314 std::string submodule,
bool isInput) {
315 if (global_port_connection.size() == i) {
321 std::set<MRRGNodeDesc>& ports_of_op = op_to_port_nodes[global_port_connection[i].first];
324 if (out_port_found.count(global_port_connection[i].first) != 0) {
325 return checkPortConn(global_port_connection, ++i, ports_used, out_port_found, op_to_port_nodes, submodule, isInput);
327 for (
auto& mrrg_node : ports_of_op) {
328 if (ports_used.count(mrrg_node) == 0) {
329 ports_used.emplace(mrrg_node);
330 if (!isInput) out_port_found.emplace(global_port_connection[i].first);
331 if (
checkPortConn(global_port_connection, ++i, ports_used, out_port_found, op_to_port_nodes, submodule, isInput)) {
334 ports_used.erase(mrrg_node);
342 std::map<
OpGraphOpDesc, std::vector<MRRGNodeDesc>>& ops_mrrg_nodes,
343 std::set<OpGraphOpDesc> exclusive_port_operation, std::string submodule,
bool isInput) {
345 std::map<MRRGNodeDesc, std::set<MRRGNodeDesc>> connected_nodes;
346 std::map<OpGraphOpDesc, std::set<MRRGNodeDesc>> op_to_port_nodes;
347 for (
const auto& op_pair : global_port_connection) {
355 std::vector<MRRGNodeDesc> nodes_to_remove;
356 for (
auto& mrrg_node : ops_mrrg_nodes[op_pair.first]) {
358 if (connected_nodes.find(mrrg_node) == connected_nodes.end()) {
359 nodes_to_remove.push_back(mrrg_node);
363 if (connected_nodes[mrrg_node].size() != 0) {
364 for (
auto& input_node : connected_nodes[mrrg_node]) {
365 op_to_port_nodes[op_pair.first].emplace(input_node);
370 for (
auto& mrrg_node : nodes_to_remove) {
371 ops_mrrg_nodes[op_pair.first].erase(remove(ops_mrrg_nodes[op_pair.first].begin(), ops_mrrg_nodes[op_pair.first].end(), mrrg_node), ops_mrrg_nodes[op_pair.first].end());
375 if (op_to_port_nodes[op_pair.first].size() == 0 && exclusive_port_operation.count(op_pair.first) == 0) {
383 }
else if (op_to_port_nodes[op_pair.first].size() == 0){
385 throw cgrame_error(
"Input ERR: cannot connect operation: " + op_pair.second->getName() +
386 " to operation: " + op_pair.first->getName() +
". \n");
388 throw cgrame_error(
"Output ERR: cannot connect operation: " + op_pair.first->getName() +
389 " to operation: " + op_pair.second->getName() +
". \n");
393 if (op_to_port_nodes.size() == 1 )
return true;
395 bool reachable =
checkPortConn(global_port_connection, 0, {}, {}, op_to_port_nodes, submodule, isInput);
398 if (op_to_port_nodes.size() < 2) {
399 throw cgrame_error(
"ERR: operation: could not connect all output/input ports. \n");
403 int min_inputs = INT_MAX;
404 for (
auto& op_port_nodes : op_to_port_nodes) {
405 if (min_inputs >= op_port_nodes.second.size()) {
406 min_inputs = op_port_nodes.second.size();
407 op_to_cluster_alone = op_port_nodes.first;
410 auto& val = op_to_cluster_alone->
output;
413 " could not not be placed. \n");
415 for (
auto& output_op : val->output){
418 for (
auto& in_val : op_to_cluster_alone->
input) {
427 std::string submodule) {
428 std::vector<MRRGNodeDesc> nodes_to_remove;
430 for (
auto source_mrrg_node : ops_mrrg_nodes[op_pair.first]) {
431 bool reached_sink_port =
false;
432 for (
auto& sink_mrrg_node : ops_mrrg_nodes[op_pair.second]) {
433 reached_sink_port =
isReachable(source_mrrg_node, sink_mrrg_node, submodule, cycles_to_sink);
434 if (reached_sink_port) {
438 if (!reached_sink_port) {
439 nodes_to_remove.push_back(source_mrrg_node);
444 for (
auto& mrrg_node : nodes_to_remove) {
445 ops_mrrg_nodes[op_pair.first].erase(remove(ops_mrrg_nodes[op_pair.first].begin(), ops_mrrg_nodes[op_pair.first].end(), mrrg_node), ops_mrrg_nodes[op_pair.first].end());
447 if (ops_mrrg_nodes[op_pair.first].empty())
return false;
455 if (ops.size() == 1)
return true;
456 std::map<OpGraphOpDesc, std::vector<MRRGNodeDesc>> ops_mrrg_nodes;
457 bool is_input_reachable =
false;
458 bool is_output_reachable =
false;
459 bool is_connected_reachable =
false;
460 std::set<OpGraphOpDesc> exclusive_input_operation;
461 std::set<OpGraphOpDesc> exclusive_output_operation;
462 std::set<OpGraphOpDesc> non_exclusive_port_operation;
463 std::vector<std::pair<OpGraphOpDesc, OpGraphOpDesc>> global_input_connection;
464 std::vector<std::pair<OpGraphOpDesc, OpGraphOpDesc>> connected_ops;
465 std::vector<std::pair<OpGraphOpDesc, OpGraphOpDesc>> global_output_connection;
466 for (
auto& operation: ops) {
468 std::vector<MRRGNodeDesc> mrrg_nodes_to_map_op;
470 ops_mrrg_nodes[operation] = mrrg_nodes_to_map_op;
473 for (
auto& in_val : operation->input) {
475 if (std::find(ops.begin(), ops.end(), connected_op) == ops.end()) {
476 global_input_connection.push_back({operation, connected_op});
477 exclusive_input_operation.emplace(operation);
482 auto& val = operation->output;
483 if (!val)
return true;
486 for (
auto& sink_op : val->output) {
487 if (std::find(ops.begin(), ops.end(), sink_op) == ops.end()) {
488 global_output_connection.push_back({operation, sink_op});
489 exclusive_output_operation.emplace(operation);
492 for (
auto& sink_op: val->output) {
493 if (operation == sink_op)
continue;
494 if (std::find(ops.begin(), ops.end(), sink_op) != ops.end()) {
495 connected_ops.push_back({operation, sink_op});
496 if (exclusive_input_operation.count(sink_op) != 0) {
497 exclusive_input_operation.erase(sink_op);
498 non_exclusive_port_operation.emplace(sink_op);
500 if (exclusive_output_operation.count(operation) != 0) {
501 exclusive_output_operation.erase(operation);
502 non_exclusive_port_operation.emplace(operation);
508 is_input_reachable =
checkPortsOfOperation(global_input_connection, ops_mrrg_nodes, exclusive_input_operation, submodule,
true );
509 if (!is_input_reachable)
return false;
510 is_output_reachable =
checkPortsOfOperation(global_output_connection, ops_mrrg_nodes, exclusive_output_operation, submodule,
false );
511 if (!is_output_reachable)
return false;
512 for (
auto& op_pair : connected_ops) {
514 if (!is_connected_reachable && non_exclusive_port_operation.count(op_pair.first) == 0 && non_exclusive_port_operation.count(op_pair.second) == 0) {
515 throw cgrame_error(
"ERR: cannot connect operation: " + op_pair.first->getName() +
516 " to operation: " + op_pair.second->getName() +
". \n");
518 else if (!is_connected_reachable) {
525 for (
auto& op_mrrg_nodes : ops_mrrg_nodes) {
526 std::vector<MRRGNodeDesc> mrrg_nodes_to_map_op;
529 if (mrrg_nodes_to_map_op.size() != op_mrrg_nodes.second.size()) {
530 for (
auto& node : op_mrrg_nodes.second) {
532 std::string name = node->name;
533 std::vector<std::string> v;
539 while ((start = name.find_first_not_of(dl,
end))
540 != std::string::npos) {
541 end = name.find(dl, start);
542 v.push_back(name.substr(start,
end - start));
544 int vec_size = v.size();
545 std::string module_operation = v[vec_size -2] +
'.' + v[vec_size -1];
555 if (val->
output.size() <= 1) {
556 throw cgrame_error(
"Op: " + source->
getName() +
" and Op: " + sink->
getName() +
" could not be clustered together or routed to one another.");
563 for (
auto& source_inputs : source->
input) {
564 l_opgraph->link(source_inputs, new_op, source_inputs->getOperandForOutput(source));
567 std::cout << val->
getName() << std::endl;
568 std::cout <<
"OUTPUTS" << std::endl;
569 for (
auto output : val->
output) {
570 std::cout << output->getName() << std::endl;
583 next_ops->push_back(nxt_op);
587 for (
auto& input : op->
input) {
588 if (!input->input)
continue;
590 next_ops->push_back(input->input);
596 if (source == sink)
return false;
599 std::vector<const MRRGNode*> fanin;
601 bool operator==(
const VertexData& rhs)
const {
602 return this->fanin == rhs.fanin && num_of_cycles == rhs.num_of_cycles;
605 using Vertex = std::pair<MRRGNodeDesc, Latency>;
607 std::queue<Vertex> to_visit;
609 std::unordered_map<Vertex, bool, pair_hash> visited;
611 auto data = std::unordered_map<Vertex, VertexData, pair_hash>();
615 to_visit.push({source, c});
616 data.insert({{source, 0}, {{source}, 0}});
618 while (!to_visit.empty() && !found) {
620 const auto explore_curr = to_visit.front().first;
621 Latency cycles_curr = to_visit.front().second;
625 if (visited[{explore_curr, cycles_curr}])
continue;
629 if (!found && sink == explore_curr) {
631 auto data_curr = data[{explore_curr, cycles_curr}];
639 for (
const auto& fanout : explore_curr->fanout) {
648 if (fanout == source)
continue;
650 if (fanout->bitwidth < sink->
bitwidth && fanout->bitwidth < source->
bitwidth)
continue;
651 auto data_curr = data[{explore_curr, cycles_curr}];
653 if (std::find(data_curr.fanin.begin(), data_curr.fanin.end(), fanout)
654 != data_curr.fanin.end())
continue;
657 if (fanout->parent->loc.x_coord != explore_curr->parent->loc.x_coord && fanout->parent->loc.y_coord != explore_curr->parent->loc.y_coord)
continue;
658 if (visited[{fanout, cycles_fanout}])
continue;
659 data[{fanout, cycles_fanout}] = {data[{explore_curr, cycles_curr}].fanin, cycles_fanout};
660 data[{fanout, cycles_fanout}].fanin.push_back(explore_curr);
661 to_visit.push({fanout, cycles_fanout});
665 visited[{explore_curr, cycles_curr}] =
true;
666 data.erase({explore_curr, cycles_curr});
674 std::vector<OpGraphOpDesc> clust;
691 std::queue<OpGraphOpDesc> operations;
692 std::set<OpGraphOpDesc> visited;
693 std::map<std::string, MRRGNodeDesc> modules_to_map_op;
701 for (
auto op : visited) {
703 for (
auto& next_op : op->output->output) {
704 operations.emplace(next_op);
710 while (!operations.empty()) {
712 auto op = operations.front();
714 if (visited.count(op) != 0)
continue;
718 if (modules_to_map_op.empty()) {
723 std::vector<OpGraphOpDesc> next_ops;
727 std::string submodule_max_ops =
"";
728 std::vector<OpGraphOpDesc> max_used_ops;
733 for (
auto& op_submodules : modules_to_map_op) {
734 std::vector<MRRGNodeDesc> used_nodes;
735 std::vector<OpGraphOpDesc> used_ops;
736 used_nodes.push_back(op_submodules.second);
737 used_ops.push_back(op);
739 visited, op_submodules.first);
740 if (max < used_ops.size()) {
741 max = used_ops.size();
742 max_used_ops = used_ops;
743 submodule_max_ops = op_submodules.first;
744 }
else if (max == used_ops.size()) {
746 max_used_ops = used_ops;
747 submodule_max_ops = op_submodules.first;
751 modules_to_map_op.clear();
763 for (
auto& next_op : op->output->output) {
764 operations.emplace(next_op);
767 for (
auto& visited_op : max_used_ops) {
768 visited.emplace(visited_op);
769 if (!visited_op->output)
continue;
770 for (
auto& next_op : visited_op->output->output) {
771 operations.emplace(next_op);
778 for (
auto& clustered_op : max_used_ops) {
783 modules_to_map_op.clear();
795 while (!operations.empty())
798 modules_to_map_op.clear();
805 for (
const auto& op :
l_opgraph->opNodes()) {
807 std::cout <<
"Final Result" << std::endl;
809 std::cout <<
"cluster" << std::endl;
810 for (
auto& op : cluster) {
811 std::cout << *op << std::endl;
814 throw cgrame_mapper_error(
"Not all ops are included in the clusters missing: " + op->getName());
820 std::cout <<
"Ops packed together: " << std::endl;
821 for (
auto& op : ops) {
822 std::cout << op->getName() <<
" ";
824 std::cout << std::endl;
827 std::cout <<
"MRRG Nodes: " << std::endl;
828 for (
auto& node : mrrg_nodes) {
829 std::cout << node->getHierarchyQualifiedName() <<
" ";
831 std::cout << std::endl;