32 std::unordered_map<std::string, std::string> fix_ports,
33 int rows,
int cols,
bool isElastic)
38 , l_fix_ports(fix_ports)
41 , l_isElastic(isElastic) {
48 for (
auto fix_port : fix_ports) {
50 if (!fixed_mrrg_node)
throw cgrame_error(
"Cannot find mrrg node for fixed operation " + fix_port.first +
" locked to node " + fix_port.second);
54 for (
auto& vector_mrrg_node : classes.function_nodes) {
55 for (
const auto& mrrg_node : vector_mrrg_node) {
60 for (
auto op : opgraph.
opNodes()) {
63 for (
auto mrrg_node : classes.function_nodes[i]) {
64 if (mrrg_node->canMapOp(op)) {
74 double final_cost = 0.0;
75 double wire_cost = 0.0;
76 float cong_cost = 0.0;
82 double cycles_to_sink;
83 float max_cycles_to_sink;
86 double latency_cost = 0;
89 size = val->output.size();
90 q = 2.79 + 0.33 * (size - 3);
91 max_cycles_to_sink = 0;
94 for (
auto& sink_op : val->output) {
106 double manhattan_dist = std::abs(source_x - sink_x) + std::abs(source_y - sink_y) + std::abs(source_z - sink_z);
107 double operation_dist = 1;
110 if (operation_dist == 0)
113 double dist = manhattan_dist;
114 double cost = std::abs(dist * operation_dist - cycles_to_sink) * cycles_to_sink;
115 latency_cost += cost;
122 final_cost = wire_cost;
124 final_cost = 0.5 * wire_cost + 0.5 * latency_cost;
162 return {x_max, x_min, y_max, y_min, z_max, z_min};
169 const auto& nref = node.second;
170 const auto& mrrg_nref = node.first;
171 const bool overuse =
l_function_nodes[mrrg_nref].occupancy > mrrg_nref->capacity;
176 for (
int i = 0; i < size_vector; i++) {
178 if (current_node == node.first) {
196 for (
int i = 0; i < size_vector; i++) {
198 if (current_node == n) {
209 std::vector<MRRGNodeDesc>& mapped_nodes =
l_mapping[op];
210 if (mapped_nodes.size() != 0) {
211 if (mapped_nodes.size() > 1)
throw cgrame_error(
"Op should only be mapped to a single node");
212 return mapped_nodes[0];
225 throw cgrame_error(
"occupancy was already zero or less");
235 throw cgrame_error(
"trying to place op at non-function node");
251 float probability = std::exp(-(delta_cost) / temperature);
257 for (
auto& op : cluster) {
267 int total_accepted = 0;
270 for (
int i = 0; i < num_swaps; i++) {
282 std::map<const OpGraphOp*, const MRRGNode*> old_placement;
283 for (
int j = 0; j < ops.size(); j++) {
297 swap(ops[j], fus[j], old_placement);
303 float delta_cost = new_cost - old_cost;
305 if (
accept(delta_cost, temperature)) {
306 if (delta_cost > 0) {
310 for (
auto op_node_pair : old_placement) {
312 placeOp(op_node_pair.first, op_node_pair.second);
319 bool mapped = mrrg_overuse && opgraph_covered;
320 const auto accept_rate = total_accepted / std::max<float>(total_tries, 1);
329 return std::make_pair(mapped, accept_rate);
335 throw make_from_stream<std::runtime_error>([&](
auto&& s) {
336 s <<
"occupancy for functional unit node " << fu
337 <<
" is more than 1, and multiple placement is not allowed";
348 if (lookup ==
l_mapping.end() || lookup->second.empty()) {
357 std::vector<MRRGNodeDesc> candidates;
358 std::vector<std::string> names_of_nodes;
365 if (names_of_nodes.size() != 0) {
366 for (
auto& name : names_of_nodes) {
367 if (fu->getHierarchyQualifiedName().find(name) != std::string::npos) {
368 candidates.push_back(fu);
372 candidates.push_back(fu);
377 if (candidates.size() < 1) {
378 throw make_from_stream<UnmappableException>([&](
auto&& s) {
387 std::vector<MRRGNodeDesc> candidates;
388 std::vector<std::string> names_of_nodes;
393 for (
auto& node : mrrg_nodes) {
396 if (names_of_nodes.size() != 0) {
397 for (
auto& name : names_of_nodes) {
398 if (node->getHierarchyQualifiedName().find(name) != std::string::npos) {
399 candidates.push_back(node);
404 candidates.push_back(node);
408 if (candidates.size() == 1) {
409 return candidates[0];
410 }
else if (candidates.size() == 0) {
419 std::vector<std::string> names_of_nodes;
420 std::vector<MRRGNodeDesc>candidates;
426 if (names_of_nodes.size() != 0) {
427 for (
auto& fu : op_candidates) {
428 for (
auto& name : names_of_nodes) {
429 if (fu->getHierarchyQualifiedName().find(name) != std::string::npos) {
430 candidates.push_back(fu);
435 candidates = op_candidates;
438 if (candidates.size() < 1) {
439 throw make_from_stream<AnnealPlacer::UnmappableException>([&](
auto&& s) {
456 if (method ==
"high_constant") {
461 cout <<
"Finding delta Costs:" << endl;
465 float max_delta_cost = 0;
467 std::vector<float> mean_of_runs;
469 std::map<const OpGraphOp*, const MRRGNode*> old_placement;
470 for (
int j = 0; j < 20; j++) {
479 for (
int k = 0; k < ops.size(); k++) {
487 swap(ops[k], fus[k], old_placement);
492 float change_cost = std::abs(
getTotalCost() - old_cost);
494 max_delta_cost = std::max(max_delta_cost, change_cost);
497 mean_of_runs.push_back(mean);
501 float standard_dev = 0.0;
502 for (
int i = 0; i < mean_of_runs.size(); i++) {
503 sum += mean_of_runs[i];
505 mean = sum / mean_of_runs.size();
506 for (
int i = 0; i < mean_of_runs.size(); i++) {
507 standard_dev += pow(mean_of_runs[i] - mean, 2.0);
509 standard_dev = sqrt(standard_dev/mean_of_runs.size());
511 return standard_dev * scale;
515 std::map<const OpGraphOp*, const MRRGNode*>& old_placement) {
521 if (second_op == op)
return;
527 std::vector<MRRGNodeDesc> nodes;
528 for (
int i = 0; i <
l_clusters[cluster_index].size(); i++) {
530 if (!op_mrrg_node)
throw cgrame_error(
"Clustering does not support hetrogenous yet");
542 old_placement.emplace(
l_clusters[cluster_index][i], f_MRRGNode);
543 old_placement.emplace(s_op, op_mrrg_node);
553 old_placement.emplace(op, first_MRRGNode);
554 old_placement.emplace(second_op, node);
559 placeOp(second_op, first_MRRGNode);
565 if (accept_rate > 0.96) {
567 }
else if (accept_rate > 0.8) {
569 }
else if (accept_rate > 0.15) {
577 (std::vector<const OpGraphOp*> cluster,
bool occupied) {
578 std::vector<MRRGNodeDesc> nodes;
580 bool has_fixed_port =
false;
581 bool satisfied =
false;
583 for (
auto& op : cluster) {
584 if (l_fix_ports.find(op->getName()) == l_fix_ports.end())
continue;
585 fixed_mrrg_node = l_mrrg.getNode(0, l_fix_ports[op->getName()]);
586 has_fixed_port =
true;
594 if (has_fixed_port) {
595 fu = fixed_mrrg_node;
598 OpGraphOpDesc clustered_op = cluster[randomUintBelow(cluster.size())];
599 fu = occupied ? getRandomFU(clustered_op) : getRandomUnoccupiedFU(clustered_op);
603 for (
auto op : cluster) {
604 const auto op_mrrg_node = getFUForOpAtLoc(op, fu->
parent->
loc);
605 if (!op_mrrg_node)
break;
606 if (l_function_nodes[op_mrrg_node].occupancy != 0 && !occupied)
break;
607 nodes.push_back(op_mrrg_node);
609 if (nodes.size() == cluster.size()) {
611 }
else if (has_fixed_port) {
612 throw cgrame_error (
"MRRG Node: " + fixed_mrrg_node->
name +
" Cannot be fixed" );
624 for (
int i = 0; i < cluster.size(); i++) {
625 bool placed =
placeOp(cluster[i], fus[i]);
627 throw cgrame_error(
"problem placing op " + cluster[i]->getName());
635 mrrg_node.second.occupancy = 0;
642 std::ofstream anneal_debug;
646 float temperature = temp;
649 cout <<
"Initial Temperature is " << temperature <<endl;
650 cout <<
"initial mapping: ";
652 cout <<
"Begin annealing" << endl;
659 for (
int iteration_num = 1;; ++iteration_num) {
660 float previous_cost = current_cost;
662 std::cout <<
"Iteration start: temp=" << temperature << std::endl;
672 anneal_debug << temperature <<
"," << current_cost << std::endl;
677 throw cgrame_error(
"There is a op that could not be mapped");
679 current_cost = current_cost == 0 ? 1 : current_cost;
681 if ((temperature < (0.05 * (current_cost/
l_clusters.size()))))
break;
689 return mapping_result;