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 <algorithm>
35 #include <cfloat>
36 #include <cmath>
37 #include <fstream>
38 #include <random>
39 #include <string>
40 #include <thread>
41 #include <unordered_map>
42 #include <vector>
43 
44 #include "block_placement.h"
45 #include "pin_alignment.h"
46 #include "shape_engine.h"
47 #include "util.h"
48 #include "utl/Logger.h"
49 
50 namespace pin_alignment {
51 using std::abs;
52 using std::cout;
53 using std::endl;
54 using std::exp;
55 using std::fstream;
56 using std::getline;
57 using std::ios;
58 using std::log;
59 using std::max;
60 using std::min;
61 using std::pair;
62 using std::pow;
63 using std::sort;
64 using std::stof;
65 using std::string;
66 using std::swap;
67 using std::thread;
68 using std::to_string;
69 using std::unordered_map;
70 using std::vector;
71 
72 using block_placement::Net;
73 using shape_engine::Cluster;
74 using shape_engine::Macro;
75 
76 using utl::Logger;
77 using utl::MPL;
78 
SimulatedAnnealingCore(const std::vector<shape_engine::Macro> & macros,const std::vector<block_placement::Net * > & nets,const std::unordered_map<std::string,std::pair<float,float>> & terminal_position,float cooling_rate,float outline_width,float outline_height,float init_prob,float rej_ratio,int max_num_step,int k,float c,int perturb_per_step,float alpha,float beta,float gamma,float flip_prob,float pos_swap_prob,float neg_swap_prob,float double_swap_prob,unsigned seed)79 SimulatedAnnealingCore::SimulatedAnnealingCore(
80     const std::vector<shape_engine::Macro>& macros,
81     const std::vector<block_placement::Net*>& nets,
82     const std::unordered_map<std::string, std::pair<float, float>>&
83         terminal_position,
84     float cooling_rate,
85     float outline_width,
86     float outline_height,
87     float init_prob,
88     float rej_ratio,
89     int max_num_step,
90     int k,
91     float c,
92     int perturb_per_step,
93     float alpha,
94     float beta,
95     float gamma,
96     float flip_prob,
97     float pos_swap_prob,
98     float neg_swap_prob,
99     float double_swap_prob,
100     unsigned seed)
101 {
102   outline_width_ = outline_width;
103   outline_height_ = outline_height;
104 
105   init_prob_ = init_prob;
106   rej_ratio_ = rej_ratio;
107   max_num_step_ = max_num_step;
108   k_ = k;
109   c_ = c;
110   perturb_per_step_ = perturb_per_step;
111   alpha_ = alpha;
112   beta_ = beta;
113   gamma_ = gamma;
114 
115   cooling_rate_ = cooling_rate;
116 
117   flip_prob_ = flip_prob;
118   pos_swap_prob_ = flip_prob_ + pos_swap_prob;
119   neg_swap_prob_ = pos_swap_prob_ + neg_swap_prob;
120   double_swap_prob_ = neg_swap_prob_ + double_swap_prob;
121 
122   nets_ = nets;
123   terminal_position_ = terminal_position;
124 
125   for (int i = 0; i < macros.size(); i++) {
126     pos_seq_.push_back(i);
127     neg_seq_.push_back(i);
128 
129     pre_pos_seq_.push_back(i);
130     pre_neg_seq_.push_back(i);
131 
132     macros_.push_back(shape_engine::Macro(macros[i]));
133 
134     macro_map_.insert(std::pair<std::string, int>(macros[i].GetName(), i));
135   }
136 
137   std::mt19937 randGen(seed);
138   generator_ = randGen;
139   std::uniform_real_distribution<float> distribution(0.0, 1.0);
140   distribution_ = distribution;
141 
142   if (macros_.size() == 1) {
143     width_ = macros_[0].GetWidth();
144     height_ = macros_[0].GetHeight();
145     area_ = width_ * height_;
146   } else {
147     // Initialize init_T_, norm_area_, norm_wirelength, norm_outline_penalty_
148     Initialize();
149   }
150 }
151 
Run()152 void SimulatedAnnealingCore::Run()
153 {
154   if (macros_.size() > 1)
155     FastSA();
156   else
157     SingleFlip();
158 }
159 
IsFeasible() const160 bool SimulatedAnnealingCore::IsFeasible() const
161 {
162   const float tolerance = 0.01;
163   return width_ <= outline_width_ * (1 + tolerance)
164     && height_ <= outline_height_ * (1 + tolerance);
165 }
166 
WriteFloorplan(const std::string & file_name) const167 void SimulatedAnnealingCore::WriteFloorplan(const std::string& file_name) const
168 {
169   std::ofstream file(file_name);
170   for (const auto& macro : macros_) {
171     file << macro.GetX() << "   ";
172     file << macro.GetY() << "   ";
173     file << macro.GetX() + macro.GetWidth() << "   ";
174     file << macro.GetY() + macro.GetHeight() << "   ";
175     file << std::endl;
176   }
177 }
178 
PackFloorplan()179 void SimulatedAnnealingCore::PackFloorplan()
180 {
181   for (auto& macro : macros_) {
182     macro.SetX(0.0);
183     macro.SetY(0.0);
184   }
185 
186   // calculate X position
187   vector<pair<int, int>> match(macros_.size());
188   for (int i = 0; i < pos_seq_.size(); i++) {
189     match[pos_seq_[i]].first = i;
190     match[neg_seq_[i]].second = i;
191   }
192 
193   vector<float> length(macros_.size(), 0.0);
194 
195   for (int i = 0; i < pos_seq_.size(); i++) {
196     int b = pos_seq_[i];
197     int p = match[b].second;
198     macros_[b].SetX(length[p]);
199     float t = macros_[b].GetX() + macros_[b].GetWidth();
200     for (int j = p; j < neg_seq_.size(); j++)
201       if (t > length[j])
202         length[j] = t;
203       else
204         break;
205   }
206 
207   width_ = length[macros_.size() - 1];
208 
209   // calulate Y position
210   vector<int> pos_seq(pos_seq_.size());
211   int num_blocks = pos_seq_.size();
212   for (int i = 0; i < num_blocks; i++)
213     pos_seq[i] = pos_seq_[num_blocks - 1 - i];
214 
215   for (int i = 0; i < num_blocks; i++) {
216     match[pos_seq[i]].first = i;
217     match[neg_seq_[i]].second = i;
218   }
219 
220   for (int i = 0; i < num_blocks; i++)
221     length[i] = 0.0;
222 
223   for (int i = 0; i < num_blocks; i++) {
224     int b = pos_seq[i];
225     int p = match[b].second;
226     macros_[b].SetY(length[p]);
227     float t = macros_[b].GetY() + macros_[b].GetHeight();
228     for (int j = p; j < num_blocks; j++)
229       if (t > length[j])
230         length[j] = t;
231       else
232         break;
233   }
234 
235   height_ = length[num_blocks - 1];
236   area_ = width_ * height_;
237 }
238 
SingleSwap(bool flag)239 void SimulatedAnnealingCore::SingleSwap(bool flag)
240 {
241   int index1 = (int) (floor((distribution_) (generator_) *macros_.size()));
242   int index2 = (int) (floor((distribution_) (generator_) *macros_.size()));
243   while (index1 == index2) {
244     index2 = (int) (floor((distribution_) (generator_) *macros_.size()));
245   }
246 
247   if (flag)
248     swap(pos_seq_[index1], pos_seq_[index2]);
249   else
250     swap(neg_seq_[index1], neg_seq_[index2]);
251 }
252 
DoubleSwap()253 void SimulatedAnnealingCore::DoubleSwap()
254 {
255   int index1 = (int) (floor((distribution_) (generator_) *macros_.size()));
256   int index2 = (int) (floor((distribution_) (generator_) *macros_.size()));
257   while (index1 == index2) {
258     index2 = (int) (floor((distribution_) (generator_) *macros_.size()));
259   }
260 
261   swap(pos_seq_[index1], pos_seq_[index2]);
262   swap(neg_seq_[index1], neg_seq_[index2]);
263 }
264 
Flip()265 void SimulatedAnnealingCore::Flip()
266 {
267   for (int i = 0; i < macros_.size(); i++)
268     macros_[i].Flip(flip_flag_);
269 }
270 
SingleFlip()271 void SimulatedAnnealingCore::SingleFlip()
272 {
273   CalculateWirelength();
274   float wirelength_best = wirelength_;
275   int action_id = 0;
276   flip_flag_ = true;
277   macros_[0].Flip(flip_flag_);
278   CalculateWirelength();
279   if (wirelength_best > wirelength_) {
280     wirelength_ = wirelength_best;
281     action_id = 1;
282   }
283 
284   flip_flag_ = false;
285   macros_[0].Flip(flip_flag_);
286   CalculateWirelength();
287   if (wirelength_best > wirelength_) {
288     wirelength_ = wirelength_best;
289     action_id = 2;
290   }
291 
292   flip_flag_ = true;
293   macros_[0].Flip(flip_flag_);
294   CalculateWirelength();
295   if (wirelength_best > wirelength_) {
296     wirelength_ = wirelength_best;
297     action_id = 3;
298   }
299 
300   if (action_id == 3) {
301     return;
302   } else {
303     flip_flag_ = false;
304     macros_[0].Flip(flip_flag_);
305     if (action_id == 0) {
306       CalculateWirelength();
307       return;
308     } else {
309       flip_flag_ = true;
310       macros_[0].Flip(flip_flag_);
311       if (action_id == 1) {
312         CalculateWirelength();
313         return;
314       } else {
315         flip_flag_ = false;
316         macros_[0].Flip(flip_flag_);
317         CalculateWirelength();
318         return;
319       }
320     }
321   }
322 }
323 
Perturb()324 void SimulatedAnnealingCore::Perturb()
325 {
326   if (macros_.size() == 1) {
327     Flip();
328     return;
329   }
330 
331   pre_pos_seq_ = pos_seq_;
332   pre_neg_seq_ = neg_seq_;
333   pre_width_ = width_;
334   pre_height_ = height_;
335   pre_area_ = area_;
336   pre_wirelength_ = wirelength_;
337   pre_outline_penalty_ = outline_penalty_;
338 
339   float op = (distribution_) (generator_);
340   if (op <= flip_prob_) {
341     action_id_ = 1;
342     float prob = (distribution_) (generator_);
343     if (prob <= 0.5)
344       flip_flag_ = true;
345     else
346       flip_flag_ = false;
347 
348     Flip();
349   } else if (op <= pos_swap_prob_) {
350     action_id_ = 2;
351     SingleSwap(true);
352   } else if (op <= neg_swap_prob_) {
353     action_id_ = 3;
354     SingleSwap(false);
355   } else {
356     action_id_ = 4;
357     DoubleSwap();
358   }
359 
360   PackFloorplan();
361 }
362 
Restore()363 void SimulatedAnnealingCore::Restore()
364 {
365   if (action_id_ == 1) {
366     Flip();
367   } else {
368     pos_seq_ = pre_pos_seq_;
369     neg_seq_ = pre_neg_seq_;
370   }
371 
372   width_ = pre_width_;
373   height_ = pre_height_;
374   area_ = pre_area_;
375   wirelength_ = pre_wirelength_;
376   outline_penalty_ = pre_outline_penalty_;
377 }
378 
CalculateOutlinePenalty()379 void SimulatedAnnealingCore::CalculateOutlinePenalty()
380 {
381   outline_penalty_ = 0.0;
382 
383   if (width_ > outline_width_ && height_ > outline_height_)
384     outline_penalty_ = width_ * height_ - outline_width_ * outline_height_;
385   else if (width_ > outline_width_ && height_ <= outline_height_)
386     outline_penalty_ = (width_ - outline_width_) * outline_height_;
387   else if (width_ <= outline_width_ && height_ > outline_height_)
388     outline_penalty_ = outline_width_ * (height_ - outline_height_);
389   else
390     outline_penalty_ = 0.0;
391 }
392 
CalculateWirelength()393 void SimulatedAnnealingCore::CalculateWirelength()
394 {
395   wirelength_ = 0.0;
396   for (Net* net : nets_) {
397     vector<string> blocks = net->blocks_;
398     vector<string> terminals = net->terminals_;
399 
400     if (blocks.size() == 0)
401       continue;
402 
403     int weight = net->weight_;
404     float lx = FLT_MAX;
405     float ly = FLT_MAX;
406     float ux = 0.0;
407     float uy = 0.0;
408 
409     for (int i = 0; i < blocks.size(); i++) {
410       float x = macros_[macro_map_[blocks[i]]].GetX()
411                 + macros_[macro_map_[blocks[i]]].GetPinX();
412       float y = macros_[macro_map_[blocks[i]]].GetY()
413                 + macros_[macro_map_[blocks[i]]].GetPinY();
414       lx = min(lx, x);
415       ly = min(ly, y);
416       ux = max(ux, x);
417       uy = max(uy, y);
418     }
419 
420     for (int i = 0; i < terminals.size(); i++) {
421       float x = terminal_position_[terminals[i]].first;
422       float y = terminal_position_[terminals[i]].second;
423       lx = min(lx, x);
424       ly = min(ly, y);
425       ux = max(ux, x);
426       uy = max(uy, y);
427     }
428 
429     wirelength_ += (abs(ux - lx) + abs(uy - ly)) * weight;
430   }
431 }
432 
NormCost(float area,float wirelength,float outline_penalty) const433 float SimulatedAnnealingCore::NormCost(float area,
434                                        float wirelength,
435                                        float outline_penalty) const
436 {
437   float cost = alpha_ * area / norm_area_;
438   if (norm_wirelength_ > 0.0)
439     cost += beta_ * wirelength_ / norm_wirelength_;
440 
441   if (norm_outline_penalty_ > 0.0)
442     cost += gamma_ * outline_penalty_ / norm_outline_penalty_;
443 
444   return cost;
445 }
446 
Initialize()447 void SimulatedAnnealingCore::Initialize()
448 {
449   vector<float> area_list;
450   vector<float> wirelength_list;
451   vector<float> outline_penalty_list;
452 
453   norm_area_ = 0.0;
454   norm_wirelength_ = 0.0;
455   norm_outline_penalty_ = 0.0;
456 
457   for (int i = 0; i < perturb_per_step_; i++) {
458     Perturb();
459     CalculateWirelength();
460     CalculateOutlinePenalty();
461 
462     area_list.push_back(area_);
463     wirelength_list.push_back(wirelength_);
464     outline_penalty_list.push_back(outline_penalty_);
465 
466     norm_area_ += area_;
467     norm_wirelength_ += wirelength_;
468     norm_outline_penalty_ = outline_penalty_;
469   }
470 
471   norm_area_ = norm_area_ / perturb_per_step_;
472   norm_wirelength_ = norm_wirelength_ / perturb_per_step_;
473   norm_outline_penalty_ = norm_outline_penalty_ / perturb_per_step_;
474 
475   vector<float> norm_cost_list;
476   float norm_cost = 0.0;
477   for (int i = 0; i < area_list.size(); i++) {
478     norm_cost
479         = NormCost(area_list[i], wirelength_list[i], outline_penalty_list[i]);
480     norm_cost_list.push_back(norm_cost);
481   }
482 
483   float delta_cost = 0.0;
484   for (int i = 1; i < norm_cost_list.size(); i++)
485     delta_cost += abs(norm_cost_list[i] - norm_cost_list[i - 1]);
486 
487   delta_cost = delta_cost / (norm_cost_list.size() - 1);
488   init_T_ = (-1) * delta_cost / log(init_prob_);
489 }
490 
FastSA()491 void SimulatedAnnealingCore::FastSA()
492 {
493   int step = 1;
494 
495   float pre_cost = NormCost(area_, wirelength_, outline_penalty_);
496   float cost = pre_cost;
497   float delta_cost = 0.0;
498   // vector<Macro> best_macros;
499   float best_cost = cost;
500   // vector<int> best_pos_seq = pos_seq_;
501   // vector<int> best_neg_seq = neg_seq_;
502 
503   float rej_num = 0.0;
504   float T = init_T_;
505   float rej_threshold = rej_ratio_ * perturb_per_step_;
506 
507   while (step <= max_num_step_ && rej_num <= rej_threshold) {
508     rej_num = 0.0;
509     for (int i = 0; i < perturb_per_step_; i++) {
510       Perturb();
511       CalculateWirelength();
512       CalculateOutlinePenalty();
513       cost = NormCost(area_, wirelength_, outline_penalty_);
514 
515       delta_cost = cost - pre_cost;
516       float num = distribution_(generator_);
517       float prob = (delta_cost > 0.0) ? exp((-1) * delta_cost / T) : 1;
518 
519       if (delta_cost <= 0 || num <= prob) {
520         pre_cost = cost;
521         if (cost < best_cost) {
522           best_cost = cost;
523           // best_pos_seq = pos_seq_;
524           // best_neg_seq = neg_seq_;
525           // best_macros = macros_;
526         }
527       } else {
528         rej_num += 1.0;
529         Restore();
530       }
531     }
532 
533     step++;
534 
535     // T = T * 0.99;
536     T = T * cooling_rate_;
537   }
538 
539   // macros_ = best_macros;
540   // pos_seq_ = best_pos_seq;
541   // neg_seq_ = best_neg_seq;
542 
543   PackFloorplan();
544 }
545 
Run(SimulatedAnnealingCore * sa)546 void Run(SimulatedAnnealingCore* sa)
547 {
548   sa->Run();
549 }
550 
ParseMacroFile(vector<Macro> & macros,float halo_width,const string & file_name)551 void ParseMacroFile(vector<Macro>& macros,
552                     float halo_width,
553                     const string& file_name)
554 {
555   unordered_map<string, pair<float, float>> pin_loc;
556   fstream f;
557   string line;
558   vector<string> content;
559   f.open(file_name, ios::in);
560   while (getline(f, line))
561     content.push_back(line);
562 
563   f.close();
564   for (int i = 0; i < content.size(); i++) {
565     vector<string> words = Split(content[i]);
566     string name = words[0];
567     float pin_x = stof(words[3]) + halo_width;
568     float pin_y = stof(words[4]) + halo_width;
569     pin_loc[name] = pair<float, float>(pin_x, pin_y);
570   }
571 
572   for (int i = 0; i < macros.size(); i++) {
573     float pin_x = pin_loc[macros[i].GetName()].first;
574     float pin_y = pin_loc[macros[i].GetName()].second;
575     macros[i].SetPinPosition(pin_x, pin_y);
576   }
577 }
578 
PinAlignmentSingleCluster(const char * report_directory,Cluster * cluster,const unordered_map<string,pair<float,float>> & terminal_position,const vector<Net * > & nets,Logger * logger,float halo_width,int num_thread,int num_run,unsigned seed)579 bool PinAlignmentSingleCluster(
580     const char *report_directory,
581     Cluster* cluster,
582     const unordered_map<string, pair<float, float>>& terminal_position,
583     const vector<Net*>& nets,
584     Logger* logger,
585     float halo_width,
586     int num_thread,
587     int num_run,
588     unsigned seed)
589 {
590   // parameterse related to fastSA
591   float init_prob = 0.95;
592   float rej_ratio = 0.99;
593   int max_num_step = 5000;
594   int k = 5;
595   float c = 100.0;
596   float alpha = 0.3;
597   float beta = 0.4;
598   float gamma = 0.3;
599   float flip_prob = 0.2;
600   float pos_swap_prob = 0.3;
601   float neg_swap_prob = 0.3;
602   float double_swap_prob = 0.2;
603 
604   string name = cluster->GetName();
605   for (int j = 0; j < name.size(); j++)
606     if (name[j] == '/')
607       name[j] = '*';
608 
609   logger->info(MPL, 3002, "Pin_Aligment Working on macro_clutser: {}", name);
610 
611   float lx = cluster->GetX();
612   float ly = cluster->GetY();
613   float ux = lx + cluster->GetWidth();
614   float uy = ly + cluster->GetHeight();
615   float outline_width = ux - lx;
616   float outline_height = uy - ly;
617 
618   // deal with macros
619   vector<Macro> macros = cluster->GetMacros();
620   //string macro_file = string("./rtl_mp/") + name + string(".txt.block");
621   string macro_file = string(report_directory) + string("/") + name + string(".txt.block");
622   ParseMacroFile(macros, halo_width, macro_file);
623 
624   int perturb_per_step = 2 * macros.size();
625 
626   std::mt19937 rand_generator(seed);
627   vector<int> seed_list;
628   for (int j = 0; j < num_thread; j++)
629     seed_list.push_back((unsigned) rand_generator());
630 
631   int remaining_run = num_run;
632   int run_thread = num_thread;
633   int sa_id = 0;
634 
635   vector<SimulatedAnnealingCore*> sa_vector;
636   vector<thread> threads;
637   while (remaining_run > 0) {
638     run_thread = num_thread;
639     if (remaining_run < num_thread)
640       run_thread = remaining_run;
641 
642     for (int j = 0; j < run_thread; j++) {
643       float cooling_rate = 0.995;
644       if (run_thread >= 2) {
645         cooling_rate = 0.995 - j * (0.995 - 0.985) / (run_thread - 1);
646       }
647 
648       SimulatedAnnealingCore* sa = new SimulatedAnnealingCore(macros,
649                                                               nets,
650                                                               terminal_position,
651                                                               cooling_rate,
652                                                               outline_width,
653                                                               outline_height,
654                                                               init_prob,
655                                                               rej_ratio,
656                                                               max_num_step,
657                                                               k,
658                                                               c,
659                                                               perturb_per_step,
660                                                               alpha,
661                                                               beta,
662                                                               gamma,
663                                                               flip_prob,
664                                                               pos_swap_prob,
665                                                               neg_swap_prob,
666                                                               double_swap_prob,
667                                                               seed_list[j]);
668 
669       sa_vector.push_back(sa);
670     }
671 
672     for (int j = 0; j < run_thread; j++)
673       threads.push_back(thread(Run, sa_vector[sa_id++]));
674 
675     for (auto& th : threads)
676       th.join();
677 
678     threads.clear();
679     remaining_run = remaining_run - run_thread;
680   }
681 
682   int min_id = -1;
683   float wirelength = FLT_MAX;
684 
685   // for(int j = 0; j < sa_vector.size(); j++) {
686   //    string file_name = string("./rtl_mp/") + name + string("_") +
687   //    to_string(j) + string("_final.txt");
688   //    sa_vector[j]->WriteFloorplan(file_name);
689   //}
690 
691   for (int j = 0; j < sa_vector.size(); j++)
692     if (sa_vector[j]->IsFeasible())
693       if (wirelength > sa_vector[j]->GetWirelength())
694         min_id = j;
695 
696   if (min_id == -1) {
697     // throw std::invalid_argument(std::string("Invalid Floorplan.  Please
698     // increase the num_run!!!"));
699     logger->info(MPL,
700                  3003,
701                  "Pin_Alignment  Cannot generate valid floorplan for current "
702                  "cluster!!!");
703     return false;
704   } else {
705     cluster->SetMacros(sa_vector[min_id]->GetMacros());
706   }
707 
708   for (int j = 0; j < sa_vector.size(); j++)
709     delete sa_vector[j];
710 
711   logger->info(MPL, 3004, "Pin_Aligment finish macro_clutser: {}", name);
712 
713   return true;
714 }
715 
716 // Pin Alignment Engine
PinAlignment(const vector<Cluster * > & clusters,Logger * logger,const char * report_directory,float halo_width,int num_thread,int num_run,unsigned seed)717 bool PinAlignment(const vector<Cluster*>& clusters,
718                   Logger* logger,
719                   const char *report_directory,
720                   float halo_width,
721                   int num_thread,
722                   int num_run,
723                   unsigned seed)
724 {
725   logger->info(MPL, 3001, "Pin_Aligment Starts");
726 
727   unordered_map<string, pair<float, float>> terminal_position;
728   vector<Net*> nets;
729 
730   // int info_id = 2;
731   for (int i = 0; i < clusters.size(); i++) {
732     if (clusters[i]->GetNumMacro() > 0) {
733       string name = clusters[i]->GetName();
734       for (int j = 0; j < name.size(); j++)
735         if (name[j] == '/')
736           name[j] = '*';
737 
738       float lx = clusters[i]->GetX();
739       float ly = clusters[i]->GetY();
740 
741       for (int j = 0; j < clusters.size(); j++) {
742         if (j != i) {
743           string terminal_name = clusters[j]->GetName();
744           float terminal_x
745               = clusters[j]->GetX() + clusters[j]->GetWidth() / 2.0;
746           float terminal_y
747               = clusters[j]->GetY() + clusters[j]->GetHeight() / 2.0;
748           terminal_x -= lx;
749           terminal_y -= ly;
750           terminal_position[terminal_name]
751               = pair<float, float>(terminal_x, terminal_y);
752         }
753       }
754 
755       // deal with nets
756       // vector<Net*> nets;
757       //string net_file = string("./rtl_mp/") + name + string(".txt.net");
758       string net_file = string(report_directory) + string("/") + name + string(".txt.net");
759       block_placement::ParseNetFile(nets, terminal_position, net_file.c_str());
760 
761       bool flag = PinAlignmentSingleCluster(report_directory,
762                                             clusters[i],
763                                             terminal_position,
764                                             nets,
765                                             logger,
766                                             halo_width,
767                                             num_thread,
768                                             num_run,
769                                             seed);
770 
771       if (flag == false)
772         return false;
773 
774       terminal_position.clear();
775       for (int j = 0; j < nets.size(); j++) {
776         delete nets[j];
777       }
778 
779       nets.clear();
780     }
781   }
782 
783   return true;
784 }
785 }  // namespace pin_alignment
786