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 <fstream>
36 #include <iostream>
37 #include <map>
38 #include <random>
39 #include <sstream>
40 #include <string>
41 #include <unordered_map>
42 #include <vector>
43
44 #include "block_placement.h"
45 #include "mpl2/rtl_mp.h"
46 #include "pin_alignment.h"
47 #include "shape_engine.h"
48 #include "util.h"
49 #include "utl/Logger.h"
50
51 using utl::PAR;
52
53 namespace mpl {
54 using block_placement::Block;
55 using shape_engine::Cluster;
56 using shape_engine::Macro;
57 using std::cout;
58 using std::endl;
59 using std::ofstream;
60 using std::string;
61 using std::to_string;
62 using std::unordered_map;
63 using std::vector;
64 using utl::Logger;
65 using utl::MPL;
66
67 template <class T>
get_param(const unordered_map<string,string> & params,const char * name,T & param,Logger * logger)68 static void get_param(const unordered_map<string, string>& params,
69 const char* name,
70 T& param,
71 Logger* logger)
72 {
73 auto iter = params.find(name);
74 if (iter != params.end()) {
75 std::istringstream s(iter->second);
76 s >> param;
77 }
78 logger->info(MPL, 9, "RTL_MP Param: {}: {}", name, param);
79 }
80
rtl_macro_placer(const char * config_file,Logger * logger,const char * report_directory,const char * report_file)81 bool rtl_macro_placer(const char* config_file,
82 Logger* logger,
83 const char* report_directory,
84 const char* report_file)
85 {
86 logger->report("*** In RTLMP ***");
87
88 string block_file = string(report_directory) + '/' + report_file + ".block";
89 string net_file = string(report_directory) + '/' + report_file + ".net";
90
91 // parameters defined in config_file
92 // These parameters are related to shape engine
93 float min_aspect_ratio = 0.33;
94 float dead_space = 0.1;
95 float halo_width = 2.0;
96
97 string region_file = string("macro_blockage.txt");
98
99 // These parameters are related to multi-start in shape engine
100 int num_thread = 5;
101 int num_run = 5;
102
103 unsigned seed = 0;
104
105 // These parameters are related to "Go with the winner"
106 float heat_rate = 0.5;
107 int num_level = 5;
108 int num_worker = 10;
109
110 // These parameters are related to cost function
111 float alpha = 0.4; // weight for area
112 float beta = 0.3; // weight for wirelength
113 float gamma = 0.3; // weight for outline penalty
114 float boundary_weight = 0.06; // weight for pushing macros to boundary
115 float macro_blockage_weight = 0.08; // weight for macro blockage
116
117 float learning_rate
118 = 0.01; // learning rate for dynamic weight in cost function
119 float shrink_factor
120 = 0.995; // shrink factor for soft blocks in simulated annealing
121 float shrink_freq
122 = 0.01; // shrink frequency for soft blocks in simulated annealing
123
124 // These parameters are related to action probabilities in each step
125 float resize_prob = 0.4;
126 float pos_swap_prob = 0.2;
127 float neg_swap_prob = 0.2;
128 float double_swap_prob = 0.2;
129
130 // These parameters are related to fastSA
131 float init_prob = 0.95;
132 float rej_ratio = 0.95;
133 int k = 50;
134 float c = 100;
135 int max_num_step = 300;
136 int perturb_per_step = 3000;
137
138 unordered_map<string, string> params = ParseConfigFile(config_file);
139
140 get_param(params, "min_aspect_ratio", min_aspect_ratio, logger);
141 get_param(params, "dead_space", dead_space, logger);
142 get_param(params, "learning_rate", learning_rate, logger);
143 get_param(params, "shrink_factor", shrink_factor, logger);
144 get_param(params, "shrink_freq", shrink_freq, logger);
145 get_param(params, "halo_width", halo_width, logger);
146 get_param(params, "region_file", region_file, logger);
147 get_param(params, "num_thread", num_thread, logger);
148 get_param(params, "num_run", num_run, logger);
149 get_param(params, "heat_rate", heat_rate, logger);
150 get_param(params, "num_level", num_level, logger);
151 get_param(params, "num_worker", num_worker, logger);
152 get_param(params, "alpha", alpha, logger);
153 get_param(params, "beta", beta, logger);
154 get_param(params, "gamma", gamma, logger);
155 get_param(params, "boundary_weight", boundary_weight, logger);
156 get_param(params, "macro_blockage_weight", macro_blockage_weight, logger);
157 get_param(params, "resize_prob", resize_prob, logger);
158 get_param(params, "pos_swap_prob", pos_swap_prob, logger);
159 get_param(params, "neg_swap_prob", neg_swap_prob, logger);
160 get_param(params, "double_swap_prob", double_swap_prob, logger);
161 get_param(params, "init_prob", init_prob, logger);
162 get_param(params, "rej_ratio", rej_ratio, logger);
163 get_param(params, "k", k, logger);
164 get_param(params, "c", c, logger);
165 get_param(params, "max_num_step", max_num_step, logger);
166 get_param(params, "perturb_per_step", perturb_per_step, logger);
167 get_param(params, "seed", seed, logger);
168
169 float outline_width = 0.0;
170 float outline_height = 0.0;
171 float outline_lx = 0.0;
172 float outline_ly = 0.0;
173
174 vector<Cluster*> clusters = shape_engine::ShapeEngine(outline_width,
175 outline_height,
176 outline_lx,
177 outline_ly,
178 min_aspect_ratio,
179 dead_space,
180 halo_width,
181 logger,
182 report_directory,
183 block_file,
184 num_thread,
185 num_run,
186 seed);
187
188 vector<Block> blocks = block_placement::Floorplan(clusters,
189 logger,
190 outline_width,
191 outline_height,
192 net_file,
193 region_file.c_str(),
194 num_level,
195 num_worker,
196 heat_rate,
197 alpha,
198 beta,
199 gamma,
200 boundary_weight,
201 macro_blockage_weight,
202 resize_prob,
203 pos_swap_prob,
204 neg_swap_prob,
205 double_swap_prob,
206 init_prob,
207 rej_ratio,
208 max_num_step,
209 k,
210 c,
211 perturb_per_step,
212 learning_rate,
213 shrink_factor,
214 shrink_freq,
215 seed);
216
217 unordered_map<string, int> block_map;
218
219 for (int i = 0; i < clusters.size(); i++)
220 block_map[blocks[i].GetName()] = i;
221
222 for (int i = 0; i < clusters.size(); i++) {
223 float x = blocks[block_map[clusters[i]->GetName()]].GetX();
224 float y = blocks[block_map[clusters[i]->GetName()]].GetY();
225 float width = blocks[block_map[clusters[i]->GetName()]].GetWidth();
226 float height = blocks[block_map[clusters[i]->GetName()]].GetHeight();
227 clusters[i]->SetPos(x, y);
228 clusters[i]->SetFootprint(width, height);
229 }
230
231 bool success_flag = pin_alignment::PinAlignment(
232 clusters, logger, report_directory, halo_width, num_thread, num_run, seed);
233
234 if (success_flag == false) {
235 logger->report("*** RTLMP Failed ***");
236 return false;
237 }
238
239
240 string openroad_filename = string("./") + string(report_directory) + "/macro_placement.cfg";
241 ofstream file;
242 file.open(openroad_filename);
243 for (int i = 0; i < clusters.size(); i++) {
244 if (clusters[i]->GetNumMacro() > 0) {
245 float cluster_lx = clusters[i]->GetX();
246 float cluster_ly = clusters[i]->GetY();
247 vector<Macro> macros = clusters[i]->GetMacros();
248 for (int j = 0; j < macros.size(); j++) {
249 string line = macros[j].GetName();
250 float lx = outline_lx + cluster_lx + macros[j].GetX() + halo_width;
251 float ly = outline_ly + cluster_ly + macros[j].GetY() + halo_width;
252 float width = macros[j].GetWidth() - 2 * halo_width;
253 float height = macros[j].GetHeight() - 2 * halo_width;
254 string orientation = macros[j].GetOrientation();
255
256 if (orientation == string("MX"))
257 line += string(" MX ") + to_string(lx) + string(" ")
258 + to_string(ly + height);
259 else if (orientation == string("MY"))
260 line += string(" MY ") + to_string(lx + width) + string(" ")
261 + to_string(ly);
262 else if (orientation == string("R180"))
263 line += string(" R180 ") + to_string(lx + width) + string(" ")
264 + to_string(ly + height);
265 else
266 line += string(" R0 ") + to_string(lx) + string(" ")
267 + to_string(ly);
268
269 file << line << endl;
270 }
271 }
272 }
273
274 file.close();
275
276 string invs_filename = string("./") + string(report_directory) + "/macro_placement.txt";
277 file.open(invs_filename);
278 for (int i = 0; i < clusters.size(); i++) {
279 if (clusters[i]->GetNumMacro() > 0) {
280 float cluster_lx = clusters[i]->GetX();
281 float cluster_ly = clusters[i]->GetY();
282 vector<Macro> macros = clusters[i]->GetMacros();
283 for (int j = 0; j < macros.size(); j++) {
284 string line = macros[j].GetName() + string(" ");
285 float lx = outline_lx + cluster_lx + macros[j].GetX() + halo_width;
286 float ly = outline_ly + cluster_ly + macros[j].GetY() + halo_width;
287 float width = macros[j].GetWidth() - 2 * halo_width;
288 float height = macros[j].GetHeight() - 2 * halo_width;
289 line += to_string(lx) + string(" ") + to_string(ly) + string(" ");
290 line += to_string(lx + width) + string(" ") + to_string(ly + height);
291 line += string(" ") + macros[j].GetOrientation();
292 file << line << endl;
293 }
294 }
295 }
296
297 file.close();
298
299 // just for quick verification
300 string floorplan_filename = string("./") + string(report_directory) + "/final_floorplan.txt";
301 file.open(floorplan_filename);
302 file << "outline_width: " << outline_width << endl;
303 file << "outline_height: " << outline_height << endl;
304 for (int i = 0; i < clusters.size(); i++) {
305 float cluster_lx = clusters[i]->GetX();
306 float cluster_ly = clusters[i]->GetY();
307 float cluster_ux = cluster_lx + clusters[i]->GetWidth();
308 float cluster_uy = cluster_ly + clusters[i]->GetHeight();
309 string cluster_name = clusters[i]->GetName();
310 file << cluster_name << " ";
311 file << cluster_lx << " ";
312 file << cluster_ly << " ";
313 file << cluster_ux << " ";
314 file << cluster_uy << " ";
315 file << endl;
316 }
317 file << endl;
318
319 for (int i = 0; i < clusters.size(); i++) {
320 if (clusters[i]->GetNumMacro() > 0) {
321 float cluster_lx = clusters[i]->GetX();
322 float cluster_ly = clusters[i]->GetY();
323 vector<Macro> macros = clusters[i]->GetMacros();
324 for (int j = 0; j < macros.size(); j++) {
325 string name = macros[j].GetName();
326 float lx = cluster_lx + macros[j].GetX() + halo_width;
327 float ly = cluster_ly + macros[j].GetY() + halo_width;
328 float width = macros[j].GetWidth() - 2 * halo_width;
329 float height = macros[j].GetHeight() - 2 * halo_width;
330 file << name << " ";
331 file << lx << " ";
332 file << ly << " ";
333 file << lx + width << " ";
334 file << ly + height << " ";
335 file << endl;
336 }
337 }
338 }
339
340 file.close();
341
342 logger->report("*** Exit RTLMP ***");
343
344 return true;
345 }
346
init(Logger * logger)347 void MacroPlacer2::init(Logger* logger)
348 {
349 logger_ = logger;
350 }
351
place(const char * config_file,const char * report_directory,const char * report_file)352 bool MacroPlacer2::place(const char* config_file,
353 const char* report_directory,
354 const char* report_file)
355 {
356 return rtl_macro_placer(config_file, logger_, report_directory, report_file);
357 }
358
359 } // namespace mpl
360