1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2021, The Regents of the University of California
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE
25 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ///////////////////////////////////////////////////////////////////////////////
33 
34 #include <float.h>
35 
36 #include <algorithm>
37 #include <cmath>
38 #include <fstream>
39 #include <random>
40 #include <thread>
41 #include <unordered_map>
42 #include <vector>
43 
44 #include "block_placement.h"
45 #include "shape_engine.h"
46 #include "util.h"
47 #include "utl/Logger.h"
48 
49 namespace block_placement {
50 using std::abs;
51 using std::cout;
52 using std::endl;
53 using std::exp;
54 using std::fstream;
55 using std::getline;
56 using std::ios;
57 using std::log;
58 using std::max;
59 using std::min;
60 using std::ofstream;
61 using std::pair;
62 using std::pow;
63 using std::sort;
64 using std::sqrt;
65 using std::stof;
66 using std::stoi;
67 using std::string;
68 using std::swap;
69 using std::thread;
70 using std::to_string;
71 using std::unordered_map;
72 using std::vector;
73 using utl::Logger;
74 using utl::MPL;
75 
Block(const std::string & name,float area,int num_macro,const std::vector<std::pair<float,float>> & aspect_ratio)76 Block::Block(const std::string& name,
77              float area,
78              int num_macro,
79              const std::vector<std::pair<float, float>>& aspect_ratio)
80 {
81   name_ = name;
82   area_ = area;
83   num_macro_ = num_macro;
84   is_soft_ = (num_macro_ == 0);
85 
86   aspect_ratio_ = aspect_ratio;
87 
88   // sort the aspect ratio according to the 1st element of the pair in
89   // ascending order And we assume the aspect_ratio[i].first <=
90   // aspect_ratio[i].second
91   std::sort(aspect_ratio_.begin(), aspect_ratio_.end());
92   for (unsigned int i = 0; i < aspect_ratio_.size(); i++) {
93     float height_low = std::sqrt(area_ * aspect_ratio_[i].first);
94     float width_high = area_ / height_low;
95 
96     float height_high = std::sqrt(area_ * aspect_ratio_[i].second);
97     float width_low = area_ / height_high;
98 
99     // height_limit_ is sorted in non-decreasing order
100     height_limit_.push_back({height_low, height_high});
101 
102     // width_limit_ is sorted in non-increasing order
103     width_limit_.push_back({width_high, width_low});
104   }
105   // Initialize shape (width_, height_) randomly
106   // ChooseAspectRatioRandom();
107 }
108 
ChangeWidth(float width)109 void Block::ChangeWidth(float width)
110 {
111   if (is_soft_ == false)
112     return;
113 
114   if (width >= width_limit_[0].first) {
115     width_ = width_limit_[0].first;
116     height_ = area_ / width_;
117   } else if (width <= width_limit_[width_limit_.size() - 1].second) {
118     width_ = width_limit_[width_limit_.size() - 1].second;
119     height_ = area_ / width_;
120   } else {
121     std::vector<std::pair<float, float>>::iterator vec_it
122         = width_limit_.begin();
123     while (vec_it->second > width)
124       vec_it++;
125 
126     if (width <= vec_it->first) {
127       width_ = width;
128       height_ = area_ / width_;
129     } else {
130       float width_low = vec_it->first;
131       vec_it--;
132       float width_high = vec_it->second;
133       if (width - width_low > width_high - width)
134         width_ = width_high;
135       else
136         width_ = width_low;
137 
138       height_ = area_ / width_;
139     }
140   }
141 }
142 
ChangeHeight(float height)143 void Block::ChangeHeight(float height)
144 {
145   if (is_soft_ == false)
146     return;
147 
148   if (height <= height_limit_[0].first) {
149     height_ = height_limit_[0].first;
150     width_ = area_ / height_;
151   } else if (height >= height_limit_[height_limit_.size() - 1].second) {
152     height_ = height_limit_[height_limit_.size() - 1].second;
153     width_ = area_ / height_;
154   } else {
155     std::vector<std::pair<float, float>>::iterator vec_it
156         = height_limit_.begin();
157     while (vec_it->second < height)
158       vec_it++;
159 
160     if (height >= vec_it->first) {
161       height_ = height;
162       width_ = area_ / height_;
163     } else {
164       float height_high = vec_it->first;
165       vec_it--;
166       float height_low = vec_it->second;
167       if (height - height_low > height_high - height)
168         height_ = height_high;
169       else
170         height_ = height_low;
171 
172       width_ = area_ / height_;
173     }
174   }
175 }
176 
ResizeHardBlock()177 void Block::ResizeHardBlock()
178 {
179   if (num_macro_ == 0 || (num_macro_ > 0 && aspect_ratio_.size() == 1)) {
180     return;
181   } else {
182     int index1
183         = (int) (floor((*distribution_)(*generator_) * aspect_ratio_.size()));
184     float ar = aspect_ratio_[index1].first;
185     float temp_ar = height_ / width_;
186     while (abs(ar - temp_ar) / ar < 0.01) {
187       index1
188           = (int) (floor((*distribution_)(*generator_) * aspect_ratio_.size()));
189       ar = aspect_ratio_[index1].first;
190       temp_ar = height_ / width_;
191     }
192 
193     height_ = std::sqrt(area_ * ar);
194     width_ = area_ / height_;
195   }
196 }
197 
ChooseAspectRatioRandom()198 void Block::ChooseAspectRatioRandom()
199 {
200   float ar = 0.0;
201   int index1
202       = (int) (floor((*distribution_)(*generator_) * aspect_ratio_.size()));
203 
204   float ar_low = aspect_ratio_[index1].first;
205   float ar_high = aspect_ratio_[index1].second;
206 
207   if (ar_low == ar_high) {
208     ar = ar_low;
209   } else {
210     float num = (*distribution_)(*generator_);
211     ar = ar_low + (ar_high - ar_low) * num;
212   }
213 
214   height_ = std::sqrt(area_ * ar);
215   width_ = area_ / height_;
216 }
217 
SetAspectRatio(float aspect_ratio)218 void Block::SetAspectRatio(float aspect_ratio)
219 {
220   height_ = std::sqrt(area_ * aspect_ratio);
221   width_ = area_ / height_;
222 }
223 
SetRandom(std::mt19937 & generator,std::uniform_real_distribution<float> & distribution)224 void Block::SetRandom(std::mt19937& generator,
225                       std::uniform_real_distribution<float>& distribution)
226 {
227   generator_ = &generator;
228   distribution_ = &distribution;
229   ChooseAspectRatioRandom();
230 }
231 
IsResizeable() const232 bool Block::IsResizeable() const
233 {
234   return num_macro_ == 0 || aspect_ratio_.size() > 1;
235 }
236 
RemoveSoftBlock()237 void Block::RemoveSoftBlock()
238 {
239   if (num_macro_ == 0) {
240     width_ = 0.0;
241     height_ = 0.0;
242   }
243 }
244 
ShrinkSoftBlock(float width_factor,float height_factor)245 void Block::ShrinkSoftBlock(float width_factor, float height_factor)
246 {
247   width_ = width_ * width_factor;
248   height_ = height_ * height_factor;
249   area_ = width_ * height_;
250 }
251 
SimulatedAnnealingCore(float outline_width,float outline_height,const std::vector<Block> & blocks,const std::vector<Net * > & nets,const std::vector<Region * > & regions,const std::unordered_map<std::string,std::pair<float,float>> & terminal_position,float cooling_rate,float alpha,float beta,float gamma,float boundary_weight,float macro_blockage_weight,float resize_prob,float pos_swap_prob,float neg_swap_prob,float double_swap_prob,float init_prob,float rej_ratio,int max_num_step,int k,float c,int perturb_per_step,float learning_rate,float shrink_factor,float shrink_freq,unsigned seed)252 SimulatedAnnealingCore::SimulatedAnnealingCore(
253     float outline_width,
254     float outline_height,
255     const std::vector<Block>& blocks,
256     const std::vector<Net*>& nets,
257     const std::vector<Region*>& regions,
258     const std::unordered_map<std::string, std::pair<float, float>>&
259         terminal_position,
260     float cooling_rate,
261     float alpha,
262     float beta,
263     float gamma,
264     float boundary_weight,
265     float macro_blockage_weight,
266     float resize_prob,
267     float pos_swap_prob,
268     float neg_swap_prob,
269     float double_swap_prob,
270     float init_prob,
271     float rej_ratio,
272     int max_num_step,
273     int k,
274     float c,
275     int perturb_per_step,
276     float learning_rate,
277     float shrink_factor,
278     float shrink_freq,
279     unsigned seed)
280 {
281   outline_width_ = outline_width;
282   outline_height_ = outline_height;
283 
284   cooling_rate_ = cooling_rate;
285 
286   learning_rate_ = learning_rate;
287   shrink_factor_ = shrink_factor;
288   shrink_freq_ = shrink_freq;
289 
290   alpha_ = alpha;
291   beta_ = beta;
292   gamma_ = gamma;
293   boundary_weight_ = boundary_weight;
294   macro_blockage_weight_ = macro_blockage_weight;
295 
296   alpha_base_ = alpha_;
297   beta_base_ = beta_;
298   gamma_base_ = gamma_;
299   boundary_weight_base_ = boundary_weight_;
300   macro_blockage_weight_base_ = macro_blockage_weight_;
301 
302   resize_prob_ = resize_prob;
303   pos_swap_prob_ = resize_prob_ + pos_swap_prob;
304   neg_swap_prob_ = pos_swap_prob_ + neg_swap_prob;
305   double_swap_prob_ = neg_swap_prob_ + double_swap_prob;
306 
307   init_prob_ = init_prob;
308   rej_ratio_ = rej_ratio;
309   max_num_step_ = max_num_step;
310   k_ = k;
311   c_ = c;
312   perturb_per_step_ = perturb_per_step;
313 
314   std::mt19937 randGen(seed);
315   generator_ = randGen;
316 
317   std::uniform_real_distribution<float> distribution(0.0, 1.0);
318   distribution_ = distribution;
319 
320   nets_ = nets;
321   regions_ = regions;
322   terminal_position_ = terminal_position;
323 
324   for (unsigned int i = 0; i < blocks.size(); i++) {
325     pos_seq_.push_back(i);
326     neg_seq_.push_back(i);
327 
328     pre_pos_seq_.push_back(i);
329     pre_neg_seq_.push_back(i);
330   }
331 
332   blocks_ = blocks;
333   for (unsigned int i = 0; i < blocks_.size(); i++) {
334     blocks_[i].SetRandom(generator_, distribution_);
335     block_map_.insert(std::pair<std::string, int>(blocks_[i].GetName(), i));
336   }
337 
338   pre_blocks_ = blocks_;
339 }
340 
PackFloorplan()341 void SimulatedAnnealingCore::PackFloorplan()
342 {
343   for (int i = 0; i < blocks_.size(); i++) {
344     blocks_[i].SetX(0.0);
345     blocks_[i].SetY(0.0);
346   }
347 
348   // calculate X position
349   vector<pair<int, int>> match(blocks_.size());
350   for (int i = 0; i < pos_seq_.size(); i++) {
351     match[pos_seq_[i]].first = i;
352     match[neg_seq_[i]].second = i;
353   }
354 
355   vector<float> length(blocks_.size());
356   for (int i = 0; i < blocks_.size(); i++)
357     length[i] = 0.0;
358 
359   for (int i = 0; i < pos_seq_.size(); i++) {
360     int b = pos_seq_[i];
361     int p = match[b].second;
362     blocks_[b].SetX(length[p]);
363     float t = blocks_[b].GetX() + blocks_[b].GetWidth();
364     for (int j = p; j < neg_seq_.size(); j++)
365       if (t > length[j])
366         length[j] = t;
367       else
368         break;
369   }
370 
371   width_ = length[blocks_.size() - 1];
372 
373   // calulate Y position
374   vector<int> pos_seq(pos_seq_.size());
375   int num_blocks = pos_seq_.size();
376   for (int i = 0; i < num_blocks; i++)
377     pos_seq[i] = pos_seq_[num_blocks - 1 - i];
378 
379   for (int i = 0; i < num_blocks; i++) {
380     match[pos_seq[i]].first = i;
381     match[neg_seq_[i]].second = i;
382   }
383 
384   for (int i = 0; i < num_blocks; i++)
385     length[i] = 0.0;
386 
387   for (int i = 0; i < num_blocks; i++) {
388     int b = pos_seq[i];
389     int p = match[b].second;
390     blocks_[b].SetY(length[p]);
391     float t = blocks_[b].GetY() + blocks_[b].GetHeight();
392     for (int j = p; j < num_blocks; j++)
393       if (t > length[j])
394         length[j] = t;
395       else
396         break;
397   }
398 
399   height_ = length[num_blocks - 1];
400   area_ = width_ * height_;
401 }
402 
SingleSwap(bool flag)403 void SimulatedAnnealingCore::SingleSwap(bool flag)
404 {
405   int index1 = (int) (floor((distribution_) (generator_) *blocks_.size()));
406   int index2 = (int) (floor((distribution_) (generator_) *blocks_.size()));
407   while (index1 == index2) {
408     index2 = (int) (floor((distribution_) (generator_) *blocks_.size()));
409   }
410 
411   if (flag)
412     swap(pos_seq_[index1], pos_seq_[index2]);
413   else
414     swap(neg_seq_[index1], neg_seq_[index2]);
415 }
416 
DoubleSwap()417 void SimulatedAnnealingCore::DoubleSwap()
418 {
419   int index1 = (int) (floor((distribution_) (generator_) *blocks_.size()));
420   int index2 = (int) (floor((distribution_) (generator_) *blocks_.size()));
421   while (index1 == index2) {
422     index2 = (int) (floor((distribution_) (generator_) *blocks_.size()));
423   }
424 
425   swap(pos_seq_[index1], pos_seq_[index2]);
426   swap(neg_seq_[index1], neg_seq_[index2]);
427 }
428 
Resize()429 void SimulatedAnnealingCore::Resize()
430 {
431   vector<int> hard_block_list;
432   vector<int> soft_block_list;
433 
434   for (int i = 0; i < blocks_.size(); i++) {
435     if (blocks_[i].GetNumMacro() > 1) {
436       hard_block_list.push_back(i);
437     } else {
438       soft_block_list.push_back(i);
439     }
440   }
441 
442   int index1 = -1;
443   float prob = (distribution_) (generator_);
444   if (prob <= hard_block_list.size() / blocks_.size()) {
445     index1 = hard_block_list[floor(
446         (distribution_) (generator_) *hard_block_list.size())];
447   } else {
448     index1 = soft_block_list[floor(
449         (distribution_) (generator_) *soft_block_list.size())];
450   }
451 
452   // int index1 = (int)(floor((distribution_)(generator_) * blocks_.size()));
453 
454   while (blocks_[index1].IsResizeable() == false) {
455     index1 = (int) (floor((distribution_) (generator_) *blocks_.size()));
456   }
457 
458   block_id_ = index1;
459 
460   if (blocks_[index1].GetNumMacro() > 0) {
461     blocks_[index1].ResizeHardBlock();
462     return;
463   }
464 
465   float option = (distribution_) (generator_);
466   if (option <= 0.2) {
467     // Change the aspect ratio of the soft block to a random value in the
468     // range of the given soft aspect-ratio constraint
469     blocks_[index1].ChooseAspectRatioRandom();
470   } else if (option <= 0.4) {
471     // Change the width of soft block to Rb = e.x2 - b.x1
472     float b_x1 = blocks_[index1].GetX();
473     float b_x2 = b_x1 + blocks_[index1].GetWidth();
474     float e_x2 = outline_width_;
475 
476     if (b_x1 >= e_x2)
477       return;
478 
479     for (int i = 0; i < blocks_.size(); i++) {
480       float cur_x2 = blocks_[i].GetX() + blocks_[i].GetWidth();
481       if (cur_x2 > b_x2 && cur_x2 < e_x2)
482         e_x2 = cur_x2;
483     }
484 
485     float width = e_x2 - b_x1;
486     blocks_[index1].ChangeWidth(width);
487   } else if (option <= 0.6) {
488     // change the width of soft block to Lb = d.x2 - b.x1
489     float b_x1 = blocks_[index1].GetX();
490     float b_x2 = b_x1 + blocks_[index1].GetWidth();
491     float d_x2 = b_x1;
492     for (int i = 0; i < blocks_.size(); i++) {
493       float cur_x2 = blocks_[i].GetX() + blocks_[i].GetWidth();
494       if (cur_x2 < b_x2 && cur_x2 > d_x2)
495         d_x2 = cur_x2;
496     }
497 
498     if (d_x2 <= b_x1) {
499       return;
500     } else {
501       float width = d_x2 - b_x1;
502       blocks_[index1].ChangeWidth(width);
503     }
504   } else if (option <= 0.8) {
505     // change the height of soft block to Tb = a.y2 - b.y1
506     float b_y1 = blocks_[index1].GetY();
507     float b_y2 = b_y1 + blocks_[index1].GetHeight();
508     float a_y2 = outline_height_;
509 
510     if (b_y1 >= a_y2)
511       return;
512 
513     for (int i = 0; i < blocks_.size(); i++) {
514       float cur_y2 = blocks_[i].GetY() + blocks_[i].GetHeight();
515       if (cur_y2 > b_y2 && cur_y2 < a_y2)
516         a_y2 = cur_y2;
517     }
518 
519     float height = a_y2 - b_y1;
520     blocks_[index1].ChangeHeight(height);
521   } else {
522     // Change the height of soft block to Bb = c.y2 - b.y1
523     float b_y1 = blocks_[index1].GetY();
524     float b_y2 = b_y1 + blocks_[index1].GetHeight();
525     float c_y2 = b_y1;
526     for (int i = 0; i < blocks_.size(); i++) {
527       float cur_y2 = blocks_[i].GetY() + blocks_[i].GetHeight();
528       if (cur_y2 < b_y2 && cur_y2 > c_y2)
529         c_y2 = cur_y2;
530     }
531 
532     if (c_y2 <= b_y1) {
533       return;
534     } else {
535       float height = c_y2 - b_y1;
536       blocks_[index1].ChangeHeight(height);
537     }
538   }
539 }
540 
Perturb()541 void SimulatedAnnealingCore::Perturb()
542 {
543   if (blocks_.size() == 1)
544     return;
545 
546   pre_pos_seq_ = pos_seq_;
547   pre_neg_seq_ = neg_seq_;
548   pre_width_ = width_;
549   pre_height_ = height_;
550   pre_area_ = area_;
551   pre_wirelength_ = wirelength_;
552   pre_outline_penalty_ = outline_penalty_;
553   pre_boundary_penalty_ = boundary_penalty_;
554   pre_macro_blockage_penalty_ = macro_blockage_penalty_;
555 
556   float op = (distribution_) (generator_);
557   if (op <= resize_prob_) {
558     action_id_ = 0;
559     pre_blocks_ = blocks_;
560     Resize();
561   } else if (op <= pos_swap_prob_) {
562     action_id_ = 1;
563     SingleSwap(true);
564   } else if (op <= neg_swap_prob_) {
565     action_id_ = 2;
566     SingleSwap(false);
567   } else {
568     action_id_ = 3;
569     DoubleSwap();
570   }
571 
572   PackFloorplan();
573 }
574 
Restore()575 void SimulatedAnnealingCore::Restore()
576 {
577   // To reduce the running time, I didn't call PackFloorplan again
578   // So when we write the final floorplan out, we need to PackFloor again
579   // at the end of SA process
580   if (action_id_ == 0)
581     blocks_[block_id_] = pre_blocks_[block_id_];
582   else if (action_id_ == 1)
583     pos_seq_ = pre_pos_seq_;
584   else if (action_id_ == 2)
585     neg_seq_ = pre_neg_seq_;
586   else {
587     pos_seq_ = pre_pos_seq_;
588     neg_seq_ = pre_neg_seq_;
589   }
590 
591   width_ = pre_width_;
592   height_ = pre_height_;
593   area_ = pre_area_;
594   wirelength_ = pre_wirelength_;
595   outline_penalty_ = pre_outline_penalty_;
596   boundary_penalty_ = pre_boundary_penalty_;
597   macro_blockage_penalty_ = pre_macro_blockage_penalty_;
598 }
599 
CalculateOutlinePenalty()600 void SimulatedAnnealingCore::CalculateOutlinePenalty()
601 {
602   outline_penalty_ = 0.0;
603 
604   float max_width = max(outline_width_, width_);
605   float max_height = max(outline_height_, height_);
606   outline_penalty_
607       = max(outline_penalty_,
608             max_width * max_height - outline_width_ * outline_height_);
609 }
610 
CalculateMacroBlockagePenalty()611 void SimulatedAnnealingCore::CalculateMacroBlockagePenalty()
612 {
613   macro_blockage_penalty_ = 0.0;
614   if (regions_.size() == 0)
615     return;
616 
617   for (Region* region : regions_) {
618     for (int i = 0; i < blocks_.size(); i++) {
619       if (blocks_[i].GetNumMacro() > 0) {
620         float lx = blocks_[i].GetX();
621         float ly = blocks_[i].GetY();
622         float ux = lx + blocks_[i].GetWidth();
623         float uy = ly + blocks_[i].GetHeight();
624 
625         float region_lx = region->lx_;
626         float region_ly = region->ly_;
627         float region_ux = region->ux_;
628         float region_uy = region->uy_;
629 
630         if (ux <= region_lx || lx >= region_ux || uy <= region_ly
631             || ly >= region_uy)
632           ;
633         else {
634           float width = min(ux, region_ux) - max(lx, region_lx);
635           float height = min(uy, region_uy) - max(ly, region_ly);
636           macro_blockage_penalty_ += width * height;
637         }
638       }
639     }
640   }
641 }
642 
CalculateBoundaryPenalty()643 void SimulatedAnnealingCore::CalculateBoundaryPenalty()
644 {
645   boundary_penalty_ = 0.0;
646   for (int i = 0; i < blocks_.size(); i++) {
647     int weight = blocks_[i].GetNumMacro();
648     if (weight > 0) {
649       float lx = blocks_[i].GetX();
650       float ly = blocks_[i].GetY();
651       float ux = lx + blocks_[i].GetWidth();
652       float uy = ly + blocks_[i].GetHeight();
653 
654       lx = min(lx, abs(outline_width_ - ux));
655       ly = min(ly, abs(outline_height_ - uy));
656       // lx = min(lx, ly);
657       lx = lx + ly;
658       boundary_penalty_ += lx;
659     }
660   }
661 }
662 
CalculateWirelength()663 void SimulatedAnnealingCore::CalculateWirelength()
664 {
665   wirelength_ = 0.0;
666   for (Net* net : nets_) {
667     vector<string> blocks = net->blocks_;
668     vector<string> terminals = net->terminals_;
669     int weight = net->weight_;
670     float lx = FLT_MAX;
671     float ly = FLT_MAX;
672     float ux = 0.0;
673     float uy = 0.0;
674 
675     for (int i = 0; i < blocks.size(); i++) {
676       float x = blocks_[block_map_[blocks[i]]].GetX()
677                 + blocks_[block_map_[blocks[i]]].GetWidth() / 2;
678       float y = blocks_[block_map_[blocks[i]]].GetY()
679                 + blocks_[block_map_[blocks[i]]].GetHeight() / 2;
680       lx = min(lx, x);
681       ly = min(ly, y);
682       ux = max(ux, x);
683       uy = max(uy, y);
684     }
685 
686     for (int i = 0; i < terminals.size(); i++) {
687       float x = terminal_position_[terminals[i]].first;
688       float y = terminal_position_[terminals[i]].second;
689       lx = min(lx, x);
690       ly = min(ly, y);
691       ux = max(ux, x);
692       uy = max(uy, y);
693     }
694 
695     wirelength_ += (abs(ux - lx) + abs(uy - ly)) * weight;
696   }
697 }
698 
NormCost(float area,float wirelength,float outline_penalty,float boundary_penalty,float macro_blockage_penalty) const699 float SimulatedAnnealingCore::NormCost(float area,
700                                        float wirelength,
701                                        float outline_penalty,
702                                        float boundary_penalty,
703                                        float macro_blockage_penalty) const
704 {
705   float cost = 0.0;
706   cost += alpha_ * area / norm_area_;
707   if (norm_wirelength_ > 0) {
708     cost += beta_ * wirelength / norm_wirelength_;
709   }
710 
711   if (norm_outline_penalty_ > 0) {
712     cost += gamma_ * outline_penalty / norm_outline_penalty_;
713   }
714 
715   if (norm_boundary_penalty_ > 0) {
716     cost += boundary_weight_ * boundary_penalty / norm_boundary_penalty_;
717   }
718 
719   if (norm_macro_blockage_penalty_ > 0) {
720     cost += macro_blockage_weight_ * macro_blockage_penalty
721             / norm_macro_blockage_penalty_;
722   }
723 
724   return cost;
725 }
726 
Initialize()727 void SimulatedAnnealingCore::Initialize()
728 {
729   vector<float> area_list;
730   vector<float> wirelength_list;
731   vector<float> outline_penalty_list;
732   vector<float> boundary_penalty_list;
733   vector<float> macro_blockage_penalty_list;
734   norm_area_ = 0.0;
735   norm_wirelength_ = 0.0;
736   norm_outline_penalty_ = 0.0;
737   norm_boundary_penalty_ = 0.0;
738   norm_macro_blockage_penalty_ = 0.0;
739   for (int i = 0; i < perturb_per_step_; i++) {
740     Perturb();
741     CalculateWirelength();
742     CalculateOutlinePenalty();
743     CalculateBoundaryPenalty();
744     CalculateMacroBlockagePenalty();
745     area_list.push_back(area_);
746     wirelength_list.push_back(wirelength_);
747     outline_penalty_list.push_back(outline_penalty_);
748     boundary_penalty_list.push_back(boundary_penalty_);
749     macro_blockage_penalty_list.push_back(macro_blockage_penalty_);
750     norm_area_ += area_;
751     norm_wirelength_ += wirelength_;
752     norm_outline_penalty_ += outline_penalty_;
753     norm_boundary_penalty_ += boundary_penalty_;
754     norm_macro_blockage_penalty_ += macro_blockage_penalty_;
755   }
756 
757   norm_area_ = norm_area_ / perturb_per_step_;
758   norm_wirelength_ = norm_wirelength_ / perturb_per_step_;
759   norm_outline_penalty_ = norm_outline_penalty_ / perturb_per_step_;
760   norm_boundary_penalty_ = norm_boundary_penalty_ / perturb_per_step_;
761   norm_macro_blockage_penalty_
762       = norm_macro_blockage_penalty_ / perturb_per_step_;
763 
764   vector<float> cost_list;
765   for (int i = 0; i < area_list.size(); i++)
766     cost_list.push_back(NormCost(area_list[i],
767                                  wirelength_list[i],
768                                  outline_penalty_list[i],
769                                  boundary_penalty_list[i],
770                                  macro_blockage_penalty_list[i]));
771 
772   float delta_cost = 0.0;
773   for (int i = 1; i < cost_list.size(); i++)
774     delta_cost += abs(cost_list[i] - cost_list[i - 1]);
775 
776   init_T_ = (-1.0) * (delta_cost / (perturb_per_step_ - 1)) / log(init_prob_);
777 }
778 
Initialize(float init_T,float norm_area,float norm_wirelength,float norm_outline_penalty,float norm_boundary_penalty,float norm_macro_blockage_penalty)779 void SimulatedAnnealingCore::Initialize(float init_T,
780                                         float norm_area,
781                                         float norm_wirelength,
782                                         float norm_outline_penalty,
783                                         float norm_boundary_penalty,
784                                         float norm_macro_blockage_penalty)
785 {
786   init_T_ = init_T;
787   norm_area_ = norm_area;
788   norm_wirelength_ = norm_wirelength;
789   norm_outline_penalty_ = norm_outline_penalty;
790   norm_boundary_penalty_ = norm_boundary_penalty;
791   norm_macro_blockage_penalty_ = norm_macro_blockage_penalty;
792 }
793 
SetSeq(const std::vector<int> & pos_seq,const std::vector<int> & neg_seq)794 void SimulatedAnnealingCore::SetSeq(const std::vector<int>& pos_seq,
795                                     const std::vector<int>& neg_seq)
796 {
797   pos_seq_ = pos_seq;
798   neg_seq_ = neg_seq;
799   pre_pos_seq_ = pos_seq;
800   pre_neg_seq_ = neg_seq;
801   PackFloorplan();
802   CalculateWirelength();
803   CalculateOutlinePenalty();
804   CalculateBoundaryPenalty();
805   CalculateMacroBlockagePenalty();
806 }
807 
IsFeasible() const808 bool SimulatedAnnealingCore::IsFeasible() const
809 {
810   float tolerance = 0.001;
811   if (width_ <= outline_width_ * (1 + tolerance)
812       && height_ <= outline_height_ * (1 + tolerance))
813     return true;
814   else
815     return false;
816 }
817 
ShrinkBlocks()818 void SimulatedAnnealingCore::ShrinkBlocks()
819 {
820   for (int i = 0; i < blocks_.size(); i++) {
821     if (blocks_[i].GetNumMacro() == 0) {
822       blocks_[i].ShrinkSoftBlock(shrink_factor_, shrink_factor_);
823     }
824   }
825 }
826 
FitFloorplan()827 bool SimulatedAnnealingCore::FitFloorplan()
828 {
829   float width_factor = outline_width_ / width_;
830   float height_factor = outline_height_ / height_;
831   vector<Block> pre_blocks = blocks_;
832   for (int i = 0; i < blocks_.size(); i++) {
833     blocks_[i].ShrinkSoftBlock(width_factor, height_factor);
834   }
835 
836   PackFloorplan();
837 
838   for (int i = 0; i < blocks_.size(); i++) {
839     if (blocks_[i].GetNumMacro() > 0) {
840       float ux = blocks_[i].GetX() + blocks_[i].GetWidth();
841       float uy = blocks_[i].GetY() + blocks_[i].GetHeight();
842       float x = blocks_[i].GetX() + 1.0 * blocks_[i].GetWidth();
843       float y = blocks_[i].GetY() + 1.0 * blocks_[i].GetHeight();
844       blocks_[i].ShrinkSoftBlock(1.0 / width_factor, 1.0 / height_factor);
845       if (ux >= outline_width_ * 0.99) {
846         x -= blocks_[i].GetWidth();
847         blocks_[i].SetX(x);
848       }
849 
850       if (uy >= outline_height_ * 0.99) {
851         y -= blocks_[i].GetHeight();
852         blocks_[i].SetY(y);
853       }
854     } else {
855       blocks_[i].ShrinkSoftBlock(1.0 / width_factor, 1.0 / height_factor);
856     }
857   }
858 
859   vector<pair<float, float>> macro_block_x_list;
860   vector<pair<float, float>> macro_block_y_list;
861 
862   for (int i = 0; i < blocks_.size(); i++) {
863     if (blocks_[i].GetNumMacro() > 0) {
864       float lx = blocks_[i].GetX();
865       float ux = lx + blocks_[i].GetWidth();
866       float ly = blocks_[i].GetY();
867       float uy = ly + blocks_[i].GetHeight();
868       macro_block_x_list.push_back(pair<float, float>(lx, ux));
869       macro_block_y_list.push_back(pair<float, float>(ly, uy));
870     }
871   }
872 
873   float overlap = 0.0;
874   for (int i = 0; i < macro_block_x_list.size(); i++) {
875     for (int j = i + 1; j < macro_block_x_list.size(); j++) {
876       float x1 = max(macro_block_x_list[i].first, macro_block_x_list[j].first);
877       float x2
878           = min(macro_block_x_list[i].second, macro_block_x_list[j].second);
879       float y1 = max(macro_block_y_list[i].first, macro_block_y_list[j].first);
880       float y2
881           = min(macro_block_y_list[i].second, macro_block_y_list[j].second);
882       float x = 0.0;
883       float y = 0.0;
884       overlap += max(x2 - x1, x) * max(y2 - y1, y);
885     }
886   }
887 
888   // We don't allow the overlap between macros and macro blockages
889   CalculateMacroBlockagePenalty();
890   if (overlap + macro_blockage_penalty_ > 0.0) {
891     blocks_ = pre_blocks;
892     PackFloorplan();
893     return false;
894   }
895 
896   return true;
897 }
898 
UpdateWeight(float avg_area,float avg_wirelength,float avg_outline_penalty,float avg_boundary_penalty,float avg_macro_blockage_penalty)899 void SimulatedAnnealingCore::UpdateWeight(float avg_area,
900                                           float avg_wirelength,
901                                           float avg_outline_penalty,
902                                           float avg_boundary_penalty,
903                                           float avg_macro_blockage_penalty)
904 {
905   avg_area = avg_area / (perturb_per_step_ * norm_area_);
906 
907   if (norm_wirelength_ != 0.0) {
908     avg_wirelength = avg_wirelength / (perturb_per_step_ * norm_wirelength_);
909   }
910 
911   if (norm_outline_penalty_ != 0.0) {
912     avg_outline_penalty
913         = avg_outline_penalty / (perturb_per_step_ * norm_outline_penalty_);
914   }
915 
916   if (norm_boundary_penalty_ != 0.0) {
917     avg_boundary_penalty
918         = avg_boundary_penalty / (perturb_per_step_ * norm_boundary_penalty_);
919   }
920 
921   if (norm_macro_blockage_penalty_ != 0.0) {
922     avg_macro_blockage_penalty
923         = avg_macro_blockage_penalty
924           / (perturb_per_step_ * norm_macro_blockage_penalty_);
925   }
926 
927   float sum_cost = avg_area + avg_wirelength + avg_outline_penalty
928                    + avg_boundary_penalty + avg_macro_blockage_penalty;
929   float new_alpha = avg_area / sum_cost;
930   float new_beta = avg_wirelength / sum_cost;
931   float new_gamma = avg_outline_penalty / sum_cost;
932   float new_boundary_weight = avg_boundary_penalty / sum_cost;
933   float new_macro_blockage_weight = avg_macro_blockage_penalty / sum_cost;
934 
935   new_alpha = alpha_base_ * (1 - new_alpha * learning_rate_);
936   new_beta = beta_base_ * (1 - new_beta * learning_rate_);
937   new_gamma = gamma_base_ * (1 - new_gamma * learning_rate_);
938   new_boundary_weight
939       = boundary_weight_base_ * (1 - new_boundary_weight * learning_rate_);
940   new_macro_blockage_weight
941       = macro_blockage_weight_base_
942         * (1 - new_macro_blockage_weight * learning_rate_);
943 
944   float new_weight = new_alpha + new_beta + new_gamma + new_boundary_weight
945                      + new_macro_blockage_weight;
946   alpha_ = new_alpha / new_weight;
947   beta_ = new_beta / new_weight;
948   gamma_ = new_gamma / new_weight;
949   boundary_weight_ = new_boundary_weight / new_weight;
950   macro_blockage_weight_ = new_macro_blockage_weight / new_weight;
951 }
952 
FastSA()953 void SimulatedAnnealingCore::FastSA()
954 {
955   float pre_cost = NormCost(area_,
956                             wirelength_,
957                             outline_penalty_,
958                             boundary_penalty_,
959                             macro_blockage_penalty_);
960   float cost = pre_cost;
961   float delta_cost = 0.0;
962 
963   float best_cost = cost;
964   // vector<Block> best_blocks = blocks_;
965   // vector<int> best_pos_seq = pos_seq_;
966   // vector<int> best_neg_seq = neg_seq_;
967 
968   float avg_area = 0.0;
969   float avg_wirelength = 0.0;
970   float avg_outline_penalty = 0.0;
971   float avg_boundary_penalty = 0.0;
972   float avg_macro_blockage_penalty = 0.0;
973 
974   int step = 1;
975   float rej_num = 0.0;
976   float T = init_T_;
977   float rej_threshold = rej_ratio_ * perturb_per_step_;
978 
979   int max_num_restart = 2;
980   int num_restart = 0;
981   int max_num_shrink = int(1.0 / shrink_freq_);
982   int num_shrink = 0;
983   int modulo_base = int(max_num_step_ * shrink_freq_);
984 
985   while (step < max_num_step_) {
986     avg_area = 0.0;
987     avg_wirelength = 0.0;
988     avg_outline_penalty = 0.0;
989     avg_boundary_penalty = 0.0;
990     avg_macro_blockage_penalty = 0.0;
991 
992     rej_num = 0.0;
993     float accept_rate = 0.0;
994     float avg_delta_cost = 0.0;
995     for (int i = 0; i < perturb_per_step_; i++) {
996       Perturb();
997       CalculateWirelength();
998       CalculateOutlinePenalty();
999       CalculateBoundaryPenalty();
1000       CalculateMacroBlockagePenalty();
1001       cost = NormCost(area_,
1002                       wirelength_,
1003                       outline_penalty_,
1004                       boundary_penalty_,
1005                       macro_blockage_penalty_);
1006 
1007       delta_cost = cost - pre_cost;
1008       float num = distribution_(generator_);
1009       float prob = (delta_cost > 0.0) ? exp((-1) * delta_cost / T) : 1;
1010       avg_delta_cost += abs(delta_cost);
1011       if (delta_cost < 0 || num < prob) {
1012         pre_cost = cost;
1013         accept_rate += 1.0;
1014         if (cost < best_cost) {
1015           best_cost = cost;
1016           // best_blocks = blocks_;
1017           // best_pos_seq = pos_seq_;
1018           // best_neg_seq = neg_seq_;
1019 
1020           if ((num_shrink <= max_num_shrink) && (step % modulo_base == 0)
1021               && (IsFeasible() == false)) {
1022             num_shrink += 1;
1023             ShrinkBlocks();
1024             PackFloorplan();
1025             CalculateWirelength();
1026             CalculateOutlinePenalty();
1027             CalculateBoundaryPenalty();
1028             CalculateMacroBlockagePenalty();
1029             pre_cost = NormCost(area_,
1030                                 wirelength_,
1031                                 outline_penalty_,
1032                                 boundary_penalty_,
1033                                 macro_blockage_penalty_);
1034             best_cost = pre_cost;
1035           }
1036         }
1037       } else {
1038         rej_num += 1.0;
1039         Restore();
1040       }
1041 
1042       avg_area += area_;
1043       avg_wirelength += wirelength_;
1044       avg_outline_penalty += outline_penalty_;
1045       avg_boundary_penalty += boundary_penalty_;
1046       avg_macro_blockage_penalty += macro_blockage_penalty_;
1047     }
1048 
1049     UpdateWeight(avg_area,
1050                  avg_wirelength,
1051                  avg_outline_penalty,
1052                  avg_boundary_penalty,
1053                  avg_macro_blockage_penalty);
1054     // cout << "step:  " << step << "  T:  " << T << " cost:  " << cost << endl;
1055 
1056     step++;
1057 
1058     /*
1059     if(step <= k_)
1060         T = init_T_ / (step * c_ * avg_delta_cost / perturb_per_step_);
1061     else
1062         T = init_T_ / (step * avg_delta_cost / perturb_per_step_);
1063     */
1064 
1065     T = T * cooling_rate_;
1066 
1067     if (step == max_num_step_) {
1068       // blocks_ = best_blocks;
1069       // pos_seq_ = best_pos_seq;
1070       // neg_seq_ = best_neg_seq;
1071 
1072       PackFloorplan();
1073       CalculateWirelength();
1074       CalculateOutlinePenalty();
1075       CalculateBoundaryPenalty();
1076       CalculateMacroBlockagePenalty();
1077       if (IsFeasible() == false) {
1078         if (num_restart < max_num_restart) {
1079           // if(FitFloorplan() == false && num_restart < max_num_restart) {
1080           // step = int(max_num_step_  * 0.5);
1081           step = 1;
1082           T = init_T_;
1083           num_restart += 1;
1084         }
1085       }
1086     }
1087   }
1088 
1089   CalculateWirelength();
1090   CalculateOutlinePenalty();
1091   CalculateBoundaryPenalty();
1092   CalculateMacroBlockagePenalty();
1093 }
1094 
Run(SimulatedAnnealingCore * sa)1095 void Run(SimulatedAnnealingCore* sa)
1096 {
1097   sa->FastSA();
1098 }
1099 
ParseNetFile(vector<Net * > & nets,unordered_map<string,pair<float,float>> & terminal_position,const string & net_file)1100 void ParseNetFile(vector<Net*>& nets,
1101                   unordered_map<string, pair<float, float>>& terminal_position,
1102                   const string& net_file)
1103 {
1104   fstream f;
1105   string line;
1106   vector<string> content;
1107   f.open(net_file, ios::in);
1108   while (getline(f, line))
1109     content.push_back(line);
1110 
1111   f.close();
1112 
1113   unordered_map<string, pair<float, float>>::iterator terminal_iter;
1114   int i = 0;
1115   while (i < content.size()) {
1116     vector<string> words = Split(content[i]);
1117     if (words.size() > 2 && words[0] == string("source:")) {
1118       string source = words[1];
1119       terminal_iter = terminal_position.find(source);
1120       bool terminal_flag = true;
1121       if (terminal_iter == terminal_position.end())
1122         terminal_flag = false;
1123 
1124       int j = 2;
1125       while (j < words.size()) {
1126         vector<string> blocks;
1127         vector<string> terminals;
1128         if (terminal_flag == true)
1129           terminals.push_back(source);
1130         else
1131           blocks.push_back(source);
1132 
1133         string sink = words[j++];
1134         terminal_iter = terminal_position.find(sink);
1135         if (terminal_iter == terminal_position.end())
1136           blocks.push_back(sink);
1137         else
1138           terminals.push_back(sink);
1139 
1140         int weight = stoi(words[j++]);
1141         Net* net = new Net(weight, blocks, terminals);
1142         nets.push_back(net);
1143       }
1144 
1145       i++;
1146     } else {
1147       i++;
1148     }
1149   }
1150 }
1151 
ParseRegionFile(vector<Region * > & regions,const string & region_file)1152 void ParseRegionFile(vector<Region*>& regions, const string& region_file)
1153 {
1154   fstream f;
1155   string line;
1156   vector<string> content;
1157   f.open(region_file, ios::in);
1158 
1159   // Check wether the file exists
1160   if (!(f.good()))
1161     return;
1162 
1163   while (getline(f, line))
1164     content.push_back(line);
1165 
1166   f.close();
1167 
1168   for (int i = 0; i < content.size(); i++) {
1169     vector<string> words = Split(content[i]);
1170     float lx = stof(words[1]);
1171     float ly = stof(words[2]);
1172     float ux = stof(words[3]);
1173     float uy = stof(words[4]);
1174     Region* region = new Region(lx, ly, ux, uy);
1175     regions.push_back(region);
1176   }
1177 }
1178 
Floorplan(const vector<shape_engine::Cluster * > & clusters,Logger * logger,float outline_width,float outline_height,const std::string & net_file,const std::string & region_file,int num_level,int num_worker,float heat_rate,float alpha,float beta,float gamma,float boundary_weight,float macro_blockage_weight,float resize_prob,float pos_swap_prob,float neg_swap_prob,float double_swap_prob,float init_prob,float rej_ratio,int max_num_step,int k,float c,int perturb_per_step,float learning_rate,float shrink_factor,float shrink_freq,unsigned seed)1179 vector<Block> Floorplan(const vector<shape_engine::Cluster*>& clusters,
1180                         Logger* logger,
1181                         float outline_width,
1182                         float outline_height,
1183                         const std::string& net_file,
1184                         const std::string& region_file,
1185                         int num_level,
1186                         int num_worker,
1187                         float heat_rate,
1188                         float alpha,
1189                         float beta,
1190                         float gamma,
1191                         float boundary_weight,
1192                         float macro_blockage_weight,
1193                         float resize_prob,
1194                         float pos_swap_prob,
1195                         float neg_swap_prob,
1196                         float double_swap_prob,
1197                         float init_prob,
1198                         float rej_ratio,
1199                         int max_num_step,
1200                         int k,
1201                         float c,
1202                         int perturb_per_step,
1203                         float learning_rate,
1204                         float shrink_factor,
1205                         float shrink_freq,
1206                         unsigned seed)
1207 {
1208   logger->info(MPL, 2001, "Block_Placement Starts");
1209 
1210   vector<Block> blocks;
1211   for (int i = 0; i < clusters.size(); i++) {
1212     string name = clusters[i]->GetName();
1213     float area = clusters[i]->GetArea();
1214     int num_macro = clusters[i]->GetNumMacro();
1215     vector<pair<float, float>> aspect_ratio = clusters[i]->GetAspectRatio();
1216     blocks.push_back(Block(name, area, num_macro, aspect_ratio));
1217   }
1218 
1219   unordered_map<string, pair<float, float>> terminal_position;
1220   string word = string("LL");
1221   terminal_position[word] = pair<float, float>(0.0, outline_height / 6.0);
1222   word = string("RL");
1223   terminal_position[word]
1224       = pair<float, float>(outline_width, outline_height / 6.0);
1225   word = string("BL");
1226   terminal_position[word] = pair<float, float>(outline_width / 6.0, 0.0);
1227   word = string("TL");
1228   terminal_position[word]
1229       = pair<float, float>(outline_width / 6.0, outline_height);
1230   word = string("LU");
1231   terminal_position[word] = pair<float, float>(0.0, outline_height * 5.0 / 6.0);
1232   word = string("RU");
1233   terminal_position[word]
1234       = pair<float, float>(outline_width, outline_height * 5.0 / 6.0);
1235   word = string("BU");
1236   terminal_position[word] = pair<float, float>(outline_width * 5.0 / 6.0, 0.0);
1237   word = string("TU");
1238   terminal_position[word]
1239       = pair<float, float>(outline_width * 5.0 / 6.0, outline_height);
1240   word = string("LM");
1241   terminal_position[word] = pair<float, float>(0.0, outline_height / 2.0);
1242   word = string("RM");
1243   terminal_position[word]
1244       = pair<float, float>(outline_width, outline_height / 2.0);
1245   word = string("BM");
1246   terminal_position[word] = pair<float, float>(outline_width / 2.0, 0.0);
1247   word = string("TM");
1248   terminal_position[word]
1249       = pair<float, float>(outline_width / 2.0, outline_height);
1250 
1251   vector<Net*> nets;
1252   ParseNetFile(nets, terminal_position, net_file);
1253 
1254   vector<Region*> regions;
1255   ParseRegionFile(regions, region_file);
1256 
1257   int num_seed = num_level * num_worker + 10;  // 10 is for guardband
1258   int seed_id = 0;
1259   vector<unsigned> seed_list(num_seed);
1260   std::mt19937 rand_generator(seed);
1261   for (int i = 0; i < num_seed; i++)
1262     seed_list[i] = (unsigned) rand_generator();
1263 
1264   SimulatedAnnealingCore* sa = new SimulatedAnnealingCore(outline_width,
1265                                                           outline_height,
1266                                                           blocks,
1267                                                           nets,
1268                                                           regions,
1269                                                           terminal_position,
1270                                                           0.99,
1271                                                           alpha,
1272                                                           beta,
1273                                                           gamma,
1274                                                           boundary_weight,
1275                                                           macro_blockage_weight,
1276                                                           resize_prob,
1277                                                           pos_swap_prob,
1278                                                           neg_swap_prob,
1279                                                           double_swap_prob,
1280                                                           init_prob,
1281                                                           rej_ratio,
1282                                                           max_num_step,
1283                                                           k,
1284                                                           c,
1285                                                           perturb_per_step,
1286                                                           learning_rate,
1287                                                           shrink_factor,
1288                                                           shrink_freq,
1289                                                           seed_list[seed_id++]);
1290 
1291   sa->Initialize();
1292   logger->info(MPL, 2002, "Block_Placement  Finish Initialization");
1293 
1294   SimulatedAnnealingCore* best_sa = nullptr;
1295   float best_cost = FLT_MAX;
1296   float norm_area = sa->GetNormArea();
1297   float norm_wirelength = sa->GetNormWirelength();
1298   float norm_outline_penalty = sa->GetNormOutlinePenalty();
1299   float norm_boundary_penalty = sa->GetNormBoundaryPenalty();
1300   float norm_macro_blockage_penalty = sa->GetNormMacroBlockagePenalty();
1301   float init_T = sa->GetInitT();
1302 
1303   logger->info(MPL, 2003, "Block_Placement Init_T: {}", init_T);
1304 
1305   blocks = sa->GetBlocks();
1306   vector<int> pos_seq = sa->GetPosSeq();
1307   vector<int> neg_seq = sa->GetNegSeq();
1308 
1309   float heat_count = 1.0;
1310 
1311   for (int i = 0; i < num_level; i++) {
1312     init_T = init_T * heat_count;
1313     heat_count = heat_count * heat_rate;
1314     vector<SimulatedAnnealingCore*> sa_vec;
1315     vector<thread> threads;
1316     float cooling_rate_step = (0.995 - 0.985) / num_worker;
1317     for (int j = 0; j < num_worker; j++) {
1318       float cooling_rate = 0.995;
1319       if (num_worker >= 2) {
1320         cooling_rate = 0.995 - j * (0.995 - 0.985) / (num_worker - 1);
1321       }
1322 
1323       // cout << "init_T:  " << init_T << endl;
1324       // cout << "thread:  " << j << "  cooling_rate:   " << cooling_rate <<
1325       // endl;
1326       SimulatedAnnealingCore* sa
1327           = new SimulatedAnnealingCore(outline_width,
1328                                        outline_height,
1329                                        blocks,
1330                                        nets,
1331                                        regions,
1332                                        terminal_position,
1333                                        cooling_rate,
1334                                        alpha,
1335                                        beta,
1336                                        gamma,
1337                                        boundary_weight,
1338                                        macro_blockage_weight,
1339                                        resize_prob,
1340                                        pos_swap_prob,
1341                                        neg_swap_prob,
1342                                        double_swap_prob,
1343                                        init_prob,
1344                                        rej_ratio,
1345                                        max_num_step,
1346                                        k,
1347                                        c,
1348                                        perturb_per_step,
1349                                        learning_rate,
1350                                        shrink_factor,
1351                                        shrink_freq,
1352                                        seed_list[seed_id++]);
1353 
1354       sa->Initialize(init_T,
1355                      norm_area,
1356                      norm_wirelength,
1357                      norm_outline_penalty,
1358                      norm_boundary_penalty,
1359                      norm_macro_blockage_penalty);
1360 
1361       sa->SetSeq(pos_seq, neg_seq);
1362       sa_vec.push_back(sa);
1363       threads.push_back(thread(Run, sa));
1364     }
1365 
1366     for (auto& th : threads)
1367       th.join();
1368 
1369     for (int j = 0; j < num_worker; j++) {
1370       if (best_cost > sa_vec[j]->GetCost()) {
1371         best_cost = sa_vec[j]->GetCost();
1372         best_sa = sa_vec[j];
1373       }
1374 
1375       // cout << "thread:  " << j << "  cost:  " << sa_vec[j]->GetCost() <<
1376       // endl;
1377     }
1378 
1379     blocks = best_sa->GetBlocks();
1380     pos_seq = best_sa->GetPosSeq();
1381     neg_seq = best_sa->GetNegSeq();
1382 
1383     // verify the result
1384     string output_info = "level:  ";
1385     output_info += to_string(i) + "   ";
1386     output_info += "cost:  ";
1387     output_info += to_string(best_sa->GetCost()) + "   ";
1388     output_info += "area:   ";
1389     output_info += to_string(best_sa->GetArea()) + "   ";
1390     output_info += "wirelength:  ";
1391     output_info += to_string(best_sa->GetWirelength()) + "   ";
1392     output_info += "outline_penalty:  ";
1393     output_info += to_string(best_sa->GetOutlinePenalty()) + "   ";
1394     output_info += "boundary_penalty:  ";
1395     output_info += to_string(best_sa->GetBoundaryPenalty()) + "   ";
1396     output_info += "macro_blockage_penalty:  ";
1397     output_info += to_string(best_sa->GetMacroBlockagePenalty());
1398 
1399     logger->info(MPL, 2004 + i, "Block_Placement {}", output_info);
1400 
1401     for (int j = 0; j < num_worker; j++) {
1402       if (best_cost < sa_vec[j]->GetCost()) {
1403         delete sa_vec[j];
1404       }
1405     }
1406   }
1407 
1408   blocks = best_sa->GetBlocks();
1409   logger->info(MPL,
1410                2004 + num_level,
1411                "Block_Placement Floorplan width: {}",
1412                best_sa->GetWidth());
1413   logger->info(MPL,
1414                2005 + num_level,
1415                "Block_Placement Floorplan height: {}",
1416                best_sa->GetHeight());
1417   logger->info(MPL,
1418                2006 + num_level,
1419                "Block_Placement Outline width: {}",
1420                outline_width);
1421   logger->info(MPL,
1422                2007 + num_level,
1423                "Block_Placement Outline height: {}",
1424                outline_height);
1425 
1426   if (!(best_sa->IsFeasible()))
1427     logger->info(
1428         MPL, 2008 + num_level, "Block_Placement No Feasible Floorplan");
1429 
1430   return blocks;
1431 }
1432 
1433 }  // namespace block_placement
1434