CGRA-ME
AnnealPlacer.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * The software programs comprising "CGRA-ME" and the documentation provided
3  * with them are copyright by its authors and the University of Toronto. Only
4  * non-commercial, not-for-profit use of this software is permitted without ex-
5  * plicit permission. This software is provided "as is" with no warranties or
6  * guarantees of support. See the LICENCE for more details. You should have re-
7  * ceived a copy of the full licence along with this software. If not, see
8  * <http://cgra-me.ece.utoronto.ca/license/>.
9  ******************************************************************************/
10 
11 #include <CGRA/ClusteredMapper.h>
12 #include <CGRA/Exception.h>
13 #include <CGRA/GraphAlgorithms.h>
14 #include <CGRA/MRRGProcedures.h>
17 #include <CGRA/dotparse.h>
18 
19 #include <algorithm>
20 #include <utility>
21 #include <functional>
22 #include <cmath>
23 #include <fstream>
24 
25 using std::cout;
26 using std::endl;
27 
29  ClusteredMapperDriver driver,
30  const OpGraph& opgraph,
31  const MRRG& mrrg,
32  std::unordered_map<std::string, std::string> fix_ports,
33  int rows, int cols, bool isElastic)
34  : ClusteredMapperDriver(driver)
35  , l_mrrg(mrrg)
36  , l_opgraph(opgraph)
37  , l_function_nodes()
38  , l_fix_ports(fix_ports)
39  , l_rows(rows + 2)
40  , l_cols(cols + 2)
41  , l_isElastic(isElastic) {
42 
43  l_II = mrrg.initiationInterval();
45 
46  const auto classes = computeNodeClassListsByCycle(mrrg);
47 
48  for (auto fix_port : fix_ports) {
49  MRRGNodeDesc fixed_mrrg_node = mrrg.getNode(0, fix_port.second);
50  if (!fixed_mrrg_node) throw cgrame_error("Cannot find mrrg node for fixed operation " + fix_port.first + " locked to node " + fix_port.second);
51  l_fixed_mrrg_nodes.emplace(fixed_mrrg_node);
52  }
53 
54  for (auto& vector_mrrg_node : classes.function_nodes) {
55  for (const auto& mrrg_node : vector_mrrg_node) {
56  l_function_nodes.emplace(mrrg_node, NodeAttributes());
57  }
58  }
59 
60  for (auto op : opgraph.opNodes()) {
61  for (int i = 0; i < mrrg.initiationInterval(); i++) {
62  if (l_op_to_nodes.find({op->getOpCode(), i}) != l_op_to_nodes.end()) continue;
63  for (auto mrrg_node : classes.function_nodes[i]) {
64  if (mrrg_node->canMapOp(op)) {
65  l_op_to_nodes[{op->getOpCode(), i}].push_back(mrrg_node);
66  }
67  }
68  }
69  }
70 
71 }
72 
74  double final_cost = 0.0;
75  double wire_cost = 0.0;
76  float cong_cost = 0.0;
77  float sum = 0;
78  float sos = 0;
79  int k = 0;
80  float size = 0;
81  double q = 0;
82  double cycles_to_sink;
83  float max_cycles_to_sink;
84  // Congestion matrix to mark the overlapping bounding boxes
85 
86  double latency_cost = 0;
87  // Looping over the different nets to get the bounding boxes
88  for (auto& val : l_opgraph.valNodes()) {
89  size = val->output.size();
90  q = 2.79 + 0.33 * (size - 3);
91  max_cycles_to_sink = 0;
92  OpGraphOpDesc source_op = val->input;
93  MRRGNodeDesc node_in = getMappedMRRGNode(source_op);
94  for (auto& sink_op : val->output) {
95  cycles_to_sink = getCyclesToSink (source_op, sink_op);
96  if (cycles_to_sink == kUndefLatency) cycles_to_sink = 1;
97  MRRGNodeDesc node_out = getMappedMRRGNode(sink_op);
98 
99  int source_x = node_in->parent->loc.x_coord;
100  int source_y = node_in->parent->loc.y_coord;
101  int source_z = node_in->getContextNum();
102 
103  int sink_x = node_out->parent->loc.x_coord;
104  int sink_y = node_out->parent->loc.y_coord;
105  int sink_z = node_out->getContextNum();
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;
108  if (!l_isElastic){
109  operation_dist = l_op_sched->getLowerBoundEdge(source_op->getOpCode(), sink_op->getOpCode());
110  if (operation_dist == 0)
111  operation_dist++;
112  }
113  double dist = manhattan_dist;
114  double cost = std::abs(dist * operation_dist - cycles_to_sink) * cycles_to_sink;
115  latency_cost += cost;
116  }
117 
118  BoundingBox bbxyz = getBB(val);
119  wire_cost += q * ((bbxyz.x_max- bbxyz.x_min) + (bbxyz.y_max - bbxyz.y_min));
120  }
121  if (l_cost_func == 0) {
122  final_cost = wire_cost;
123  } if (l_cost_func == 1) {
124  final_cost = 0.5 * wire_cost + 0.5 * latency_cost;
125  }
126  return final_cost;
127 }
128 
130  MRRGNodeDesc node_in = getMappedMRRGNode(val->input);
131  int x_min = node_in->parent->loc.x_coord;
132  int x_max = node_in->parent->loc.x_coord;
133  int y_min = node_in->parent->loc.y_coord;
134  int y_max = node_in->parent->loc.y_coord;
135  int z_max = node_in->getContextNum();
136  int z_min = node_in->getContextNum();
137 
138  for (OpGraph::OpDescriptor op : val->output) {
139  MRRGNodeDesc node_out = getMappedMRRGNode(op);
140  if (node_out->parent->loc.x_coord < x_min) {
141  x_min = node_out->parent->loc.x_coord;
142  }
143  if (node_out->parent->loc.x_coord > x_max) {
144  x_max = node_out->parent->loc.x_coord;
145  }
146 
147  if (node_out->parent->loc.y_coord < y_min) {
148  y_min = node_out->parent->loc.y_coord;
149  }
150  if (node_out->parent->loc.y_coord > y_max) {
151  y_max = node_out->parent->loc.y_coord;
152  }
153 
154  if (node_out->getContextNum() < z_min) {
155  z_min = node_out->getContextNum();
156  }
157  if (node_out->getContextNum() > z_max) {
158  z_max = node_out->getContextNum();
159  }
160  }
161 
162  return {x_max, x_min, y_max, y_min, z_max, z_min};
163 }
164 
165 // Checks if there are any node is overused
167  bool result = true;
168  for (const auto& node : l_function_nodes) {
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;
172  if (overuse && l_verbosity > 0) {
173  int size_vector = l_opgraph.opNodes().size();
174  OpGraph::OpDescriptor return_ptr = nullptr;
175  OpGraph::NodeDescriptor node_ptr = nullptr;
176  for (int i = 0; i < size_vector; i++) {
177  const auto current_node = getMappedMRRGNode(l_opgraph.opNodes()[i]);
178  if (current_node == node.first) {
179  return_ptr = l_opgraph.opNodes()[i];
180  }
181  }
182  }
183  result &= !overuse;
184  }
185  return result;
186 }
187 
188 // Get the op that is mapped at the passed mrrg node
190  int size_vector = l_opgraph.opNodes().size();
191 
192  OpGraph::OpDescriptor return_ptr = nullptr;
193 
194  // loop through all op nodes to find same MRRG node as 'this'
195  // may be very slow
196  for (int i = 0; i < size_vector; i++) {
197  const auto current_node = getMappedMRRGNode(l_opgraph.opNodes()[i]);
198  if (current_node == n) {
199  return_ptr = l_opgraph.opNodes()[i];
200  break;
201  }
202  }
203 
204  return return_ptr;
205 }
206 
207 // Return the MRRG node that the op is assigned to
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];
213  }
214 
215  return {}; // return null if unmapped
216 }
217 
218 
219 // Rips up Op as well as routes in and out (if they exist) and records the cost of whatever was ripped up
220 // if a pointer to cost is given, the cost is also returned
222  // unmap all nodes
223  for (auto& n : l_mapping[op]) {
224  if (l_function_nodes[n].occupancy-- <= 0) {
225  throw cgrame_error("occupancy was already zero or less");
226  }
227  }
228  l_mapping[op].clear();
229  return;
230 }
231 
232 // Place the following op into the given mrrg node
235  throw cgrame_error("trying to place op at non-function node");
236  }
237  if (l_mapping[op].size() != 0) // Make sure this op is not placed anywhere else
238  return false;
239 
240  l_mapping[op].push_back(n);
241  l_function_nodes[n].occupancy++;
242 
243  return true;
244 }
245 
246 // Accept the following swap depending on the temprature and the delta cost
247 bool AnnealPlacer::accept(float delta_cost, float temperature) const {
248  if (delta_cost < 0)
249  return true;
250 
251  float probability = std::exp(-(delta_cost) / temperature);
252  return probability > randomRealBetween0And1();
253 }
254 
255 // Check if one of the ops of the cluster is fixed or not
256 bool AnnealPlacer::isClusterFixed(std::vector<OpGraph::OpDescriptor> cluster) {
257  for (auto& op : cluster) {
258  if (l_fix_ports.find(op->getName()) == l_fix_ports.end()) continue;
259  return true;
260  }
261  return false;
262 }
263 
264 
265 std::pair<bool, float> AnnealPlacer::inner_place_and_route_loop(float temperature) {
266  int num_swaps = l_opgraph.opNodes().size() * l_swap_factor;
267  int total_accepted = 0;
268  int total_tries = 0;
269 
270  for (int i = 0; i < num_swaps; i++) {
271  int vector_size = l_clusters.size();
272  int index = randomUintBelow(vector_size);
273  auto ops = l_clusters.at(index);
274  if (isClusterFixed(ops)) continue;
275  const auto fus = getRandomFUs(ops, true);
276  if (fus.at(0) == getMappedMRRGNode(ops.at(0))) // make sure that it is a different FU
277  continue;
278  // This is an actual attempt to swap
279  total_tries++;
280  // find the cost of this selected op
281  double old_cost = getTotalCost();
282  std::map<const OpGraphOp*, const MRRGNode*> old_placement;
283  for (int j = 0; j < ops.size(); j++) {
284  // check if occupied
285  if (l_function_nodes[fus[j]].occupancy < fus[j]->capacity) {
286  // move there
287  old_placement.emplace(ops[j], getMappedMRRGNode(ops[j]));
288  ripUpOp(ops[j]);
289  placeOp(ops[j], fus[j]);
290 
291 
292  } else { // there must only be one unit mapped here
293  assertOccupancyLimit(fus[j]);
294  // swap, rip off two nodes?
295  // first find the op node corresponding to this mrrg node
296  // keep track of op's MRRG Node
297  swap(ops[j], fus[j], old_placement);
298  }
299  }
300 
301  // get new cost
302  double new_cost = getTotalCost();
303  float delta_cost = new_cost - old_cost;
304 
305  if (accept(delta_cost, temperature)) {
306  if (delta_cost > 0) {
307  total_accepted++;
308  }
309  } else { // restore changes
310  for (auto op_node_pair : old_placement) {
311  ripUpOp(op_node_pair.first);
312  placeOp(op_node_pair.first, op_node_pair.second);
313  }
314  }
315  }
316 
317  bool mrrg_overuse = checkOveruse();
318  bool opgraph_covered = isOpgraphCovered();
319  bool mapped = mrrg_overuse && opgraph_covered;
320  const auto accept_rate = total_accepted / std::max<float>(total_tries, 1);
321 
322  if (l_verbosity > 1) {
323  //std::cout << "overuse_ok=" << mrrg_overuse << " total_cost=" << getTotalCost();
324  //std::cout << " opgraph_covered=" << opgraph_covered << " opgraph_cost=" << getOpGraphCost();
325  //std::cout << " accept_rate=" << total_accepted << '/' << total_tries << '=' << accept_rate;
326  //std::cout << std::endl;
327  }
328 
329  return std::make_pair(mapped, accept_rate);
330 }
331 
333  auto& fu_ref = l_function_nodes[fu];
334  if (l_function_nodes[fu].occupancy > 1) {
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";
338  });
339  }
340 }
341 
342 
344  // having any nodes mapped is sufficient:
345  // re-computation not supported, and we never partially route a value
346  for (const auto& op : l_opgraph.opNodes()) {
347  auto lookup = l_mapping.find(op);
348  if (lookup == l_mapping.end() || lookup->second.empty()) {
349  return false;
350  }
351  }
352  return true;
353 }
354 
355 // get a random unoccupied FU
357  std::vector<MRRGNodeDesc> candidates;
358  std::vector<std::string> names_of_nodes;
359  if (l_ops_to_node_names.find(op) != l_ops_to_node_names.end()) {
360  names_of_nodes = l_ops_to_node_names[op];
361  }
362 
363  for (const auto& fu : l_op_to_nodes[{op->getOpCode(), l_schedule[op] % l_II}]) {
364  if (fu->canMapOp(op) && l_function_nodes[fu].occupancy < fu->capacity && l_fixed_mrrg_nodes.count(fu) == 0) {
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);
369  }
370  }
371  } else {
372  candidates.push_back(fu);
373  }
374  }
375  }
376 
377  if (candidates.size() < 1) {
378  throw make_from_stream<UnmappableException>([&](auto&& s) {
379  s << "Impossible to place op " << l_opgraph.getNodeRef(op);
380  });
381  }
382 
383  return candidates[randomUintBelow(candidates.size())];
384 }
385 
387  std::vector<MRRGNodeDesc> candidates; // = grid[op->getOpCode()][loc.x_coord][loc.y_coord];
388  std::vector<std::string> names_of_nodes;
389 
390  std::vector<MRRGNodeDesc> mrrg_nodes = l_op_to_nodes[{op->getOpCode(), l_schedule[op] % l_II}];
391  if (l_ops_to_node_names.find(op) != l_ops_to_node_names.end())
392  names_of_nodes = l_ops_to_node_names[op];
393  for (auto& node : mrrg_nodes) {
394  Module* parent = node->parent;
395  if (node->canMapOp(op) && parent->loc.x_coord == loc.x_coord && parent->loc.y_coord == loc.y_coord && (l_fixed_mrrg_nodes.count(node) == 0 || l_fix_ports.find(op->getName()) != l_fix_ports.end())) {
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);
400  break;
401  }
402  }
403  } else {
404  candidates.push_back(node);
405  }
406  }
407  }
408  if (candidates.size() == 1) {
409  return candidates[0];
410  } else if (candidates.size() == 0) {
411  return NULL;
412  }
413  return candidates[randomUintBelow(candidates.size())];
414 }
415 
416 // generate a random FU
418  std::vector<MRRGNodeDesc> op_candidates = l_op_to_nodes[{op->getOpCode(), l_schedule[op] % l_II}];
419  std::vector<std::string> names_of_nodes;
420  std::vector<MRRGNodeDesc>candidates;
421 
422  if (l_ops_to_node_names.find(op) != l_ops_to_node_names.end()) {
423  names_of_nodes = l_ops_to_node_names[op];
424  }
425 
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);
431  }
432  }
433  }
434  } else {
435  candidates = op_candidates;
436  }
437 
438  if (candidates.size() < 1) {
439  throw make_from_stream<AnnealPlacer::UnmappableException>([&](auto&& s) {
440  s << "Impossible to place op " << l_opgraph.getNodeRef(op);
441  });
442  }
443 
444  bool fixed = true;
445  MRRGNodeDesc new_node;
446  while (fixed) {
447  new_node = candidates[randomUintBelow(candidates.size())];
448  if (l_fixed_mrrg_nodes.find(new_node) == l_fixed_mrrg_nodes.end()) break;
449  }
450 
451  return new_node;
452 }
453 
455  const auto& method = l_mapper_args.getString("initial_temperature_method");
456  if (method == "high_constant") {
457  return 1000000.0;
458  }
459 
460  if (l_verbosity > 0) {
461  cout << "Finding delta Costs:" << endl;
462  cout << "Total Cost: " << getTotalCost() << endl;
463  }
464 
465  float max_delta_cost = 0;
466  double old_cost = getTotalCost();
467  std::vector<float> mean_of_runs;
468  // Do 100x of perturbation
469  std::map<const OpGraphOp*, const MRRGNode*> old_placement;
470  for (int j = 0; j < 20; j++) {
471  float mean = 0.0;
472  for (int i = 0; i < l_clusters.size(); i++) {
473  // choose a random op
474  int vector_size = l_clusters.size();
475  int index = randomUintBelow(vector_size);
476  auto ops = l_clusters.at(index);
477  if (isClusterFixed(ops)) continue;
478  const auto fus = getRandomFUs(ops, true);
479  for (int k = 0; k < ops.size(); k++) {
480  if (l_function_nodes[fus[k]].occupancy < fus[k]->capacity) {
481  // if unoccupied, move there
482  ripUpOp(ops[k]);
483  placeOp(ops[k], fus[k]);
484  } else {
485  // if occupied, swap
486  assertOccupancyLimit(fus[k]);
487  swap(ops[k], fus[k], old_placement);
488  }
489  }
490 
491  // see how the cost changed
492  float change_cost = std::abs(getTotalCost() - old_cost);
493  mean += change_cost;
494  max_delta_cost = std::max(max_delta_cost, change_cost);
495  }
496  mean /= l_clusters.size();
497  mean_of_runs.push_back(mean);
498  }
499  float sum = 0.0;
500  float mean = 0.0;
501  float standard_dev = 0.0;
502  for (int i = 0; i < mean_of_runs.size(); i++) {
503  sum += mean_of_runs[i];
504  }
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);
508  }
509  standard_dev = sqrt(standard_dev/mean_of_runs.size());
510 
511  return standard_dev * scale;
512 }
513 
515  std::map<const OpGraphOp*, const MRRGNode*>& old_placement) {
516  // swap, rip off two nodes?
517  // first find the op node corresponding to this mrrg node
518  // keep track of op's MRRG Node
519  // check if the second op is the same as the current op
520  const auto second_op = getOpMapedAt(node);
521  if (second_op == op) return;
522 
523  const auto first_MRRGNode = getMappedMRRGNode(op);
524  // If there is a cluster then swap all the nodes of the cluster
525  int cluster_index = l_op_cluster_index[second_op];
526  if (l_clusters[cluster_index].size() > 1) {
527  std::vector<MRRGNodeDesc> nodes;
528  for (int i = 0; i < l_clusters[cluster_index].size(); i++) {
529  const auto op_mrrg_node = getFUForOpAtLoc(l_clusters[cluster_index][i], first_MRRGNode->parent->loc);
530  if (!op_mrrg_node) throw cgrame_error("Clustering does not support hetrogenous yet");
531  // check if occupied
532  if (l_function_nodes[op_mrrg_node].occupancy < op_mrrg_node->capacity) {
533  // move there
534  old_placement.emplace(l_clusters[cluster_index][i], getMappedMRRGNode(l_clusters[cluster_index][i]));
535  ripUpOp(l_clusters[cluster_index][i]);
536  placeOp(l_clusters[cluster_index][i], op_mrrg_node);
537 
538 
539  } else { // there must only be one unit mapped here
540  const auto s_op = getOpMapedAt(op_mrrg_node);
541  const auto f_MRRGNode = getMappedMRRGNode(l_clusters[cluster_index][i]);
542  old_placement.emplace(l_clusters[cluster_index][i], f_MRRGNode);
543  old_placement.emplace(s_op, op_mrrg_node);
544 
545  ripUpOp(l_clusters[cluster_index][i]);
546  ripUpOp(s_op);
547  placeOp(l_clusters[cluster_index][i], op_mrrg_node);
548  placeOp(s_op, f_MRRGNode);
549  }
550  }
551 
552  } else {
553  old_placement.emplace(op, first_MRRGNode);
554  old_placement.emplace(second_op, node);
555 
556  ripUpOp(op);
557  ripUpOp(second_op);
558  placeOp(op, node);
559  placeOp(second_op, first_MRRGNode);
560  }
561  return;
562 }
563 
564 float AnnealPlacer::nextTemperature(float t, float accept_rate) const {
565  if (accept_rate > 0.96) {
566  return t * 0.5;
567  } else if (accept_rate > 0.8) {
568  return t * 0.9;
569  } else if (accept_rate > 0.15) {
570  return t * 0.95;
571  } else {
572  return t * 0.8;
573  }
574 }
575 
576 std::vector<MRRG::NodeDescriptor> AnnealPlacer::getRandomFUs
577  (std::vector<const OpGraphOp*> cluster, bool occupied) {
578  std::vector<MRRGNodeDesc> nodes;
579  const MRRGNode* fixed_mrrg_node;
580  bool has_fixed_port = false;
581  bool satisfied = false;
582 
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;
587  break;
588  }
589 
590  // Loops break once all op nodes in a cluster could be placed to the
591  // same place
592  while (!satisfied) {
594  if (has_fixed_port) {
595  fu = fixed_mrrg_node;
596  } else {
597  // Getting a random FU for a random operation in the cluster
598  OpGraphOpDesc clustered_op = cluster[randomUintBelow(cluster.size())];
599  fu = occupied ? getRandomFU(clustered_op) : getRandomUnoccupiedFU(clustered_op);
600  }
601  // For each node in the cluster gather the mrrg nodes that relates to
602  // the location
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);
608  }
609  if (nodes.size() == cluster.size()) {
610  satisfied = true;
611  } else if (has_fixed_port) {
612  throw cgrame_error ("MRRG Node: " + fixed_mrrg_node->name + " Cannot be fixed" );
613  } else {
614  nodes.clear();
615  }
616  }
617  return nodes;
618 }
619 
621  // randomized initial placement
622  for (auto& cluster : l_clusters) {
623  auto fus = getRandomFUs(cluster, false);
624  for (int i = 0; i < cluster.size(); i++) {
625  bool placed = placeOp(cluster[i], fus[i]);
626  if (!placed) {
627  throw cgrame_error("problem placing op " + cluster[i]->getName());
628  }
629  }
630  }
631 }
632 
634  for (auto& mrrg_node : l_function_nodes) {
635  mrrg_node.second.occupancy = 0;
636  }
637  l_mapping.clear();
638 }
639 
641  Mapping mapping_result = l_empty_mapping_result; // Create result obj
642  std::ofstream anneal_debug;
643 
644  // Set radius and temprature
645  // const float initial_temperature = determineInitialTemperature();
646  float temperature = temp;
647 
648  if (l_verbosity > 1) {
649  cout << "Initial Temperature is " << temperature <<endl;
650  cout << "initial mapping: ";
651  printMapping();
652  cout << "Begin annealing" << endl;
653  }
654 
655  // Getting intial cost
656  double current_cost = getTotalCost();
657  bool mapped = false;
658 
659  for (int iteration_num = 1;; ++iteration_num) {
660  float previous_cost = current_cost;
661  if (l_verbosity > 1) {
662  std::cout << "Iteration start: temp=" << temperature << std::endl;
663  }
664 
665  // do a bunch of swaps at the current temperature
666  float accept_rate;
667  std::tie(mapped, accept_rate) = inner_place_and_route_loop(temperature);
668 
669  // Get the new cost after swaps
670  current_cost = getTotalCost();
671  if (anneal_debug) {
672  anneal_debug << temperature << "," << current_cost << std::endl;
673  }
674 
675  // Exit if there is a problem with mapping an operation
676  if (!mapped) {
677  throw cgrame_error("There is a op that could not be mapped");
678  }
679  current_cost = current_cost == 0 ? 1 : current_cost;
680  // Break once the temprature becomes cold
681  if ((temperature < (0.05 * (current_cost/l_clusters.size())))) break;
682 
683  // post-iteration updates
684  temperature = nextTemperature(temperature, accept_rate);
685  }
686 
687  printMapping();
688  if (mapped) setMappingInto(mapping_result);
689  return mapping_result;
690 }
691 
Location::x_coord
unsigned x_coord
Definition: Module.h:157
AnnealPlacer::l_isElastic
bool l_isElastic
Definition: ClusteredMapper.h:330
AnnealPlacer::l_function_nodes
std::map< const MRRGNode *, NodeAttributes > l_function_nodes
Definition: ClusteredMapper.h:339
OpGraphVal::output
std::vector< OpGraphOp * > output
Definition: OpGraph.h:196
ClusteredMapperDriver::l_op_sched
OpScheduler * l_op_sched
Definition: ClusteredMapper.h:86
ClusteredMapperDriver::l_cost_func
const int l_cost_func
Definition: ClusteredMapper.h:85
MRRG_NODE_ROUTING_FUNCTION
@ MRRG_NODE_ROUTING_FUNCTION
Definition: MRRG.h:47
CodeProfiling.h
AnnealPlacer::placeOp
bool placeOp(OpGraphOpDesc op, MRRGNodeDesc n)
Definition: AnnealPlacer.cpp:233
AnnealPlacer::getTotalCost
double getTotalCost()
Definition: AnnealPlacer.cpp:73
MRRG
Definition: MRRG.h:216
dotparse.h
AnnealPlacer::getRandomFUs
std::vector< MRRGNodeDesc > getRandomFUs(std::vector< OpGraphOpDesc > ops, bool occupied)
Definition: AnnealPlacer.cpp:577
ClusteredMapperDriver::l_schedule
std::unordered_map< OpGraphOpDesc, int > l_schedule
Definition: ClusteredMapper.h:90
GraphAlgorithms.h
Location
Definition: Module.h:156
ClusteredMapperDriver
Proxy class that makes a new instance of the for ever call. Holds constant configuration info,...
Definition: ClusteredMapper.h:41
MRRGNode::type
MRRGNode_Type type
Definition: MRRG.h:107
OpGraph::getNodeRef
OpGraphOp & getNodeRef(OpDescriptor ndesc)
Definition: OpGraph.h:376
BoundingBox::y_min
int y_min
Definition: ClusteredMapper.h:108
AnnealPlacer::setInitialPlacement
void setInitialPlacement()
Definition: AnnealPlacer.cpp:620
AnnealPlacer::l_op_to_nodes
std::unordered_map< OpCodeByCycle, std::vector< MRRGNodeDesc >, pair_hash > l_op_to_nodes
Definition: ClusteredMapper.h:342
OpScheduler::getLowerBoundEdge
int getLowerBoundEdge(OpGraphOpCode op1, OpGraphOpCode op2)
Definition: OpScheduler.h:74
AnnealPlacer::checkOveruse
bool checkOveruse()
Definition: AnnealPlacer.cpp:166
Module::parent
Module * parent
Definition: Module.h:243
OpGraph::valNodes
auto & valNodes() const
Definition: OpGraph.h:314
BoundingBox::y_max
int y_max
Definition: ClusteredMapper.h:107
AnnealPlacer::clearPlacement
void clearPlacement()
Definition: AnnealPlacer.cpp:633
MRRGNode::getContextNum
auto getContextNum() const
Definition: MRRG.h:124
computeNodeClassListsByCycle
MRRGNodeClassListsByCycle computeNodeClassListsByCycle(const MRRG &mrrg)
Definition: MRRGProcedures.cpp:138
AnnealPlacer::getOpMapedAt
OpGraphOpDesc getOpMapedAt(MRRGNodeDesc n)
Definition: AnnealPlacer.cpp:189
AnnealPlacer::placeOpGraph
Mapping placeOpGraph(float temp)
Definition: AnnealPlacer.cpp:640
ClusteredMapperDriver::l_op_cluster_index
std::map< OpGraphOpDesc, int > l_op_cluster_index
Definition: ClusteredMapper.h:88
AnnealPlacer::assertOccupancyLimit
void assertOccupancyLimit(MRRGNodeDesc fu)
Definition: AnnealPlacer.cpp:332
BoundingBox::x_max
int x_max
Definition: ClusteredMapper.h:105
OpGraphOp::input
std::vector< OpGraphVal * > input
Definition: OpGraph.h:164
MRRGNode::parent
Module * parent
Definition: MRRG.h:119
AnnealPlacer::inner_place_and_route_loop
std::pair< bool, float > inner_place_and_route_loop(float temp)
The main body of one iteration.
Definition: AnnealPlacer.cpp:265
AnnealPlacer::l_fix_ports
std::unordered_map< std::string, std::string > l_fix_ports
Definition: ClusteredMapper.h:338
AnnealPlacer::l_fixed_mrrg_nodes
std::set< MRRGNodeDesc > l_fixed_mrrg_nodes
Definition: ClusteredMapper.h:336
Mapping
Definition: Mapping.h:31
Exception.h
AnnealPlacer::l_opgraph
const OpGraph & l_opgraph
Definition: ClusteredMapper.h:332
AnnealPlacer::getRandomUnoccupiedFU
MRRGNodeDesc getRandomUnoccupiedFU(OpGraphOpDesc op)
gets the functional units to map the op
Definition: AnnealPlacer.cpp:356
ClusteredMapperDriver::l_ops_to_node_names
std::unordered_map< OpGraphOpDesc, std::vector< std::string > > l_ops_to_node_names
Definition: ClusteredMapper.h:89
OpGraph::opNodes
auto & opNodes() const
Definition: OpGraph.h:313
AnnealPlacer::getBB
BoundingBox getBB(OpGraphValDesc)
does the costing of the fopgraph
Definition: AnnealPlacer.cpp:129
AnnealPlacer::l_II
int l_II
Definition: ClusteredMapper.h:329
MRRG_NODE_FUNCTION
@ MRRG_NODE_FUNCTION
Definition: MRRG.h:46
UserModules.h
AnnealPlacer::l_randomInt
std::minstd_rand l_randomInt
Definition: ClusteredMapper.h:337
ClusteredMapperDriver::getCyclesToSink
const Latency getCyclesToSink(OpGraphOpDesc source, OpGraphOpDesc sink)
Definition: ClusteredMapper.cpp:217
Module
Definition: Module.h:163
OpGraphNode
Definition: OpGraph.h:113
ClusteredMapperDriver::l_empty_mapping_result
Mapping l_empty_mapping_result
Definition: ClusteredMapper.h:91
AnnealPlacer::isOpgraphCovered
bool isOpgraphCovered() const
Checks if the opgraph mapping is valid.
Definition: AnnealPlacer.cpp:343
AnnealPlacer::printMapping
void printMapping() const
Definition: ClusteredMapper.h:320
AnnealPlacer::accept
bool accept(float delta_cost, float temperature) const
Should a move with this delta_cost be accepted at this temperature?
Definition: AnnealPlacer.cpp:247
AnnealPlacer::nextTemperature
float nextTemperature(float t, float accept_rate) const
Definition: AnnealPlacer.cpp:564
ClusteredMapperDriver::l_mapper_args
const ConfigStore l_mapper_args
Definition: ClusteredMapper.h:84
AnnealPlacer::randomUintBelow
std::size_t randomUintBelow(std::size_t past_end) const
Definition: ClusteredMapper.h:344
OpGraphVal
Definition: OpGraph.h:178
AnnealPlacer::getMappedMRRGNode
MRRGNodeDesc getMappedMRRGNode(OpGraphOpDesc op)
gets the mrrgnode associated with an op or the op associated with an mrrgnode
Definition: AnnealPlacer.cpp:208
OpGraphOp
Definition: OpGraph.h:131
MRRGNode
Definition: MRRG.h:60
OpGraphOp::getOpCode
auto getOpCode() const
Definition: OpGraph.h:156
ConfigStore::getString
const std::string & getString(const std::string &key) const
Definition: ConfigStore.h:136
AnnealPlacer::getRandomFU
MRRGNodeDesc getRandomFU(OpGraphOpDesc op)
Definition: AnnealPlacer.cpp:417
MRRG::getNode
NodeDescriptor getNode(int cycle, const std::string &name) const
Definition: MRRG.cpp:142
ClusteredMapperDriver::l_verbosity
const int l_verbosity
Definition: ClusteredMapper.h:79
AnnealPlacer::swap
void swap(OpGraphOpDesc op, MRRGNodeDesc node, std::map< OpGraphOpDesc, MRRGNodeDesc > &old_placement)
Definition: AnnealPlacer.cpp:514
AnnealPlacer::determineTemperature
float determineTemperature(float scale)
Definition: AnnealPlacer.cpp:454
NodeAttributes
Definition: ClusteredMapper.h:95
Module::loc
Location loc
Definition: Module.h:239
OpGraphVal::input
OpGraphOp * input
Definition: OpGraph.h:190
MRRG::initiationInterval
int initiationInterval() const
Definition: MRRG.h:346
AnnealPlacer::isClusterFixed
bool isClusterFixed(std::vector< OpGraphOpDesc > cluster)
Definition: AnnealPlacer.cpp:256
MRRGProcedures.h
ClusteredMapperDriver::l_rand_seed
const int l_rand_seed
Definition: ClusteredMapper.h:71
ClusteredMapperDriver::l_swap_factor
const int l_swap_factor
Definition: ClusteredMapper.h:76
AnnealPlacer::getFUForOpAtLoc
MRRGNodeDesc getFUForOpAtLoc(OpGraphOpDesc op, Location loc)
Definition: AnnealPlacer.cpp:386
BoundingBox::x_min
int x_min
Definition: ClusteredMapper.h:106
AnnealPlacer::setMappingInto
void setMappingInto(Mapping &m) const
Definition: ClusteredMapper.h:313
ClusteredMapperDriver::kUndefLatency
static constexpr Latency kUndefLatency
Definition: ClusteredMapper.h:42
BoundingBox
Definition: ClusteredMapper.h:104
ClusteredMapperDriver::l_clusters
std::vector< std::vector< OpGraphOpDesc > > l_clusters
Definition: ClusteredMapper.h:87
ClusteredMapper.h
OpGraph
Definition: OpGraph.h:215
AnnealPlacer::ripUpOp
void ripUpOp(OpGraphOpDesc op)
places and removes an op from an mrrgnode
Definition: AnnealPlacer.cpp:221
AnnealPlacer::AnnealPlacer
AnnealPlacer(ClusteredMapperDriver driver, const OpGraph &opgraph, const MRRG &mrrg, std::unordered_map< std::string, std::string > fix_ports, int rows, int cols, bool isElastic=false)
Definition: AnnealPlacer.cpp:28
MRRGNode::name
std::string name
Definition: MRRG.h:106
cgrame_error
Definition: Exception.h:20
AnnealPlacer::randomRealBetween0And1
double randomRealBetween0And1() const
Definition: ClusteredMapper.h:345
AnnealPlacer::l_mapping
std::map< OpGraph::NodeDescriptor, std::vector< MRRGNodeDesc > > l_mapping
Definition: ClusteredMapper.h:340
OpGraphNode::getName
const std::string & getName() const
Definition: OpGraph.h:121
Location::y_coord
unsigned y_coord
Definition: Module.h:158