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