|
1 | | -utl::set_metrics_stage "floorplan__{}" |
2 | | -source $::env(SCRIPTS_DIR)/load.tcl |
3 | | -load_design 1_synth.odb 1_synth.sdc |
| 1 | +# Enable keeping variables between stages |
| 2 | +set ::env(KEEP_VARS) 1 |
4 | 3 |
|
5 | 4 | # Floorplan |
6 | | - |
7 | | -proc report_unused_masters { } { |
8 | | - set db [ord::get_db] |
9 | | - set libs [$db getLibs] |
10 | | - set masters "" |
11 | | - foreach lib $libs { |
12 | | - foreach master [$lib getMasters] { |
13 | | - # filter out non-block masters, or you can remove this conditional to detect any unused master |
14 | | - if { [$master getType] == "BLOCK" } { |
15 | | - lappend masters $master |
16 | | - } |
17 | | - } |
18 | | - } |
19 | | - |
20 | | - set block [ord::get_db_block] |
21 | | - set insts [$block getInsts] |
22 | | - |
23 | | - foreach inst $insts { |
24 | | - set inst_master [$inst getMaster] |
25 | | - set masters [lsearch -all -not -inline $masters $inst_master] |
26 | | - } |
27 | | - |
28 | | - foreach master $masters { |
29 | | - puts "Master [$master getName] is loaded but not used in the design" |
30 | | - } |
31 | | -} |
32 | | - |
33 | | -report_unused_masters |
34 | | - |
35 | | -#Run check_setup |
36 | | -puts "\n==========================================================================" |
37 | | -puts "Floorplan check_setup" |
38 | | -puts "--------------------------------------------------------------------------" |
39 | | -check_setup |
40 | | - |
41 | | -set num_instances [llength [get_cells -hier *]] |
42 | | -puts "number instances in verilog is $num_instances" |
43 | | - |
44 | | -set additional_args "" |
45 | | -append_env_var additional_args ADDITIONAL_SITES -additional_sites 1 |
46 | | - |
47 | | -# Check which floorplan initialization method is specified (mutually exclusive) |
48 | | -set use_floorplan_def [env_var_exists_and_non_empty FLOORPLAN_DEF] |
49 | | -set use_footprint [env_var_exists_and_non_empty FOOTPRINT] |
50 | | -set use_die_and_core_area \ |
51 | | - [expr { [env_var_exists_and_non_empty DIE_AREA] && [env_var_exists_and_non_empty CORE_AREA] }] |
52 | | -set use_core_utilization [env_var_exists_and_non_empty CORE_UTILIZATION] |
53 | | - |
54 | | -# Enforce mutual exclusion - exactly one method must be specified |
55 | | -set methods_defined \ |
56 | | - [expr { $use_floorplan_def + $use_footprint + $use_die_and_core_area + $use_core_utilization }] |
57 | | -if { $methods_defined > 1 } { |
58 | | - puts "Error: Floorplan initialization methods are mutually exclusive, pick one." |
59 | | - exit 1 |
60 | | -} |
61 | | - |
62 | | -# Method 1: Use existing DEF file with floorplan data |
63 | | -if { $use_floorplan_def } { |
64 | | - log_cmd read_def -floorplan_initialize $env(FLOORPLAN_DEF) |
65 | | - # Method 2: Use ICeWall footprint file (platform-specific extension) |
66 | | -} elseif { $use_footprint } { |
67 | | - ICeWall load_footprint $env(FOOTPRINT) |
68 | | - |
69 | | - initialize_floorplan \ |
70 | | - -die_area [ICeWall get_die_area] \ |
71 | | - -core_area [ICeWall get_core_area] \ |
72 | | - -site $::env(PLACE_SITE) |
73 | | - |
74 | | - ICeWall init_footprint $env(SIG_MAP_FILE) |
75 | | - # Method 3: Use explicit die and core area coordinates |
76 | | -} elseif { $use_die_and_core_area } { |
77 | | - initialize_floorplan -die_area $::env(DIE_AREA) \ |
78 | | - -core_area $::env(CORE_AREA) \ |
79 | | - -site $::env(PLACE_SITE) \ |
80 | | - {*}$additional_args |
81 | | - # Method 4: Calculate core area from utilization, aspect ratio, and margins |
82 | | -} elseif { $use_core_utilization } { |
83 | | - initialize_floorplan -utilization $::env(CORE_UTILIZATION) \ |
84 | | - -aspect_ratio $::env(CORE_ASPECT_RATIO) \ |
85 | | - -core_space $::env(CORE_MARGIN) \ |
86 | | - -site $::env(PLACE_SITE) \ |
87 | | - {*}$additional_args |
88 | | -} else { |
89 | | - puts "Error: No floorplan initialization method specified" |
90 | | - exit 1 |
91 | | -} |
92 | | - |
93 | | -# Create routing tracks: MAKE_TRACKS script, platform make_tracks.tcl, or make_tracks command |
94 | | -if { [env_var_exists_and_non_empty MAKE_TRACKS] } { |
95 | | - log_cmd source $::env(MAKE_TRACKS) |
96 | | -} elseif { [file exists $::env(PLATFORM_DIR)/make_tracks.tcl] } { |
97 | | - log_cmd source $::env(PLATFORM_DIR)/make_tracks.tcl |
98 | | -} else { |
99 | | - make_tracks |
100 | | -} |
101 | | - |
102 | | -# Configure global routing: FASTROUTE_TCL script or |
103 | | -# set_global_routing_layer_adjustment/set_routing_layers |
104 | | -if { [env_var_exists_and_non_empty FASTROUTE_TCL] } { |
105 | | - log_cmd source $::env(FASTROUTE_TCL) |
106 | | -} else { |
107 | | - log_cmd \ |
108 | | - set_global_routing_layer_adjustment \ |
109 | | - $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) $::env(ROUTING_LAYER_ADJUSTMENT) |
110 | | - log_cmd set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) |
111 | | -} |
112 | | - |
113 | | -source_env_var_if_exists FOOTPRINT_TCL |
114 | | - |
115 | | -if { ![env_var_equal SKIP_REPAIR_TIE_FANOUT 1] } { |
116 | | - # This needs to come before any call to remove_buffers. You could have one |
117 | | - # tie driving multiple buffers that drive multiple outputs. |
118 | | - # Repair tie lo fanout |
119 | | - puts "Repair tie lo fanout..." |
120 | | - set tielo_cell_name [lindex $::env(TIELO_CELL_AND_PORT) 0] |
121 | | - set tielo_lib_name [get_name [get_property [lindex [get_lib_cell $tielo_cell_name] 0] library]] |
122 | | - set tielo_pin $tielo_lib_name/$tielo_cell_name/[lindex $::env(TIELO_CELL_AND_PORT) 1] |
123 | | - repair_tie_fanout -separation $::env(TIE_SEPARATION) $tielo_pin |
124 | | - |
125 | | - # Repair tie hi fanout |
126 | | - puts "Repair tie hi fanout..." |
127 | | - set tiehi_cell_name [lindex $::env(TIEHI_CELL_AND_PORT) 0] |
128 | | - set tiehi_lib_name [get_name [get_property [lindex [get_lib_cell $tiehi_cell_name] 0] library]] |
129 | | - set tiehi_pin $tiehi_lib_name/$tiehi_cell_name/[lindex $::env(TIEHI_CELL_AND_PORT) 1] |
130 | | - repair_tie_fanout -separation $::env(TIE_SEPARATION) $tiehi_pin |
131 | | -} |
132 | | - |
133 | | -if { [env_var_exists_and_non_empty SWAP_ARITH_OPERATORS] } { |
134 | | - estimate_parasitics -placement |
135 | | - replace_arith_modules |
136 | | -} |
137 | | - |
138 | | -if { [env_var_equals REMOVE_ABC_BUFFERS 1] } { |
139 | | - # remove buffers inserted by yosys/abc |
140 | | - remove_buffers |
141 | | -} else { |
142 | | - # Skip clone & split |
143 | | - set ::env(SETUP_MOVE_SEQUENCE) "unbuffer,sizeup,swap,buffer,vt_swap" |
144 | | - set ::env(SKIP_LAST_GASP) 1 |
145 | | - set additional_args_repair_timing "" |
146 | | - append_env_var additional_args_repair_timing MAX_REPAIR_TIMING_ITER -max_iterations 1 |
147 | | - repair_timing_helper -setup {*}$additional_args_repair_timing |
148 | | -} |
149 | | - |
150 | | -puts "Default units for flow" |
151 | | -report_units |
152 | | -report_units_metric |
153 | | -report_metrics 2 "floorplan final" false false |
154 | | - |
155 | | -source_env_var_if_exists POST_FLOORPLAN_TCL |
156 | | -source_env_var_if_exists IO_CONSTRAINTS |
157 | | - |
158 | | -write_db $::env(RESULTS_DIR)/2_1_floorplan.odb |
159 | | -write_sdc -no_timestamp $::env(RESULTS_DIR)/2_1_floorplan.sdc |
160 | | - |
| 5 | +source $::env(SCRIPTS_DIR)/floorplan.tcl |
161 | 6 |
|
162 | 7 | # Macro placement |
163 | | -source $::env(SCRIPTS_DIR)/macro_place_util.tcl |
164 | | - |
165 | | -write_db $::env(RESULTS_DIR)/2_2_floorplan_macro.odb |
166 | | -write_macro_placement $::env(RESULTS_DIR)/2_2_floorplan_macro.tcl |
167 | | - |
| 8 | +source $::env(SCRIPTS_DIR)/macro_place.tcl |
168 | 9 |
|
169 | 10 | # Tapcell insertion |
170 | | -if { [env_var_exists_and_non_empty TAPCELL_TCL] } { |
171 | | - source $::env(TAPCELL_TCL) |
172 | | -} else { |
173 | | - cut_rows |
174 | | -} |
175 | | - |
176 | | -write_db $::env(RESULTS_DIR)/2_3_floorplan_tapcell.odb |
| 11 | +source $::env(SCRIPTS_DIR)/tapcell.tcl |
177 | 12 |
|
178 | 13 | # PDN |
179 | | -source $::env(PDN_TCL) |
180 | | -pdngen |
181 | | - |
182 | | -source_env_var_if_exists POST_PDN_TCL |
183 | | - |
184 | | -# Check all supply nets |
185 | | -set block [ord::get_db_block] |
186 | | -foreach net [$block getNets] { |
187 | | - set type [$net getSigType] |
188 | | - if { $type == "POWER" || $type == "GROUND" } { |
189 | | - # Temporarily disable due to CI issues |
190 | | - # puts "Check supply: [$net getName]" |
191 | | - # check_power_grid -net [$net getName] |
192 | | - } |
193 | | -} |
194 | | - |
195 | | -write_db $::env(RESULTS_DIR)/2_4_floorplan_pdn.odb |
| 14 | +source $::env(SCRIPTS_DIR)/pdn.tcl |
196 | 15 |
|
197 | 16 | # Global placement skipping IOs |
198 | | -if { [env_var_exists_and_non_empty FLOORPLAN_DEF] } { |
199 | | - puts "FLOORPLAN_DEF is set. Skipping global placement without IOs" |
200 | | -} elseif { [all_pins_placed] } { |
201 | | - puts "All pins are placed. Skipping global placement without IOs" |
202 | | -} else { |
203 | | - log_cmd global_placement -skip_io -density [place_density_with_lb_addon] \ |
204 | | - -pad_left $::env(CELL_PAD_IN_SITES_GLOBAL_PLACEMENT) \ |
205 | | - -pad_right $::env(CELL_PAD_IN_SITES_GLOBAL_PLACEMENT) \ |
206 | | - {*}[env_var_or_empty GLOBAL_PLACEMENT_ARGS] |
207 | | -} |
208 | | - |
209 | | -write_db $::env(RESULTS_DIR)/3_1_place_gp_skip_io.odb |
| 17 | +source $::env(SCRIPTS_DIR)/global_place_skip_io.tcl |
210 | 18 |
|
211 | 19 | # IO placement |
212 | | -if { |
213 | | - ![env_var_exists_and_non_empty FLOORPLAN_DEF] && |
214 | | - ![env_var_exists_and_non_empty FOOTPRINT] && |
215 | | - ![env_var_exists_and_non_empty FOOTPRINT_TCL] |
216 | | -} { |
217 | | - # load_design 3_1_place_gp_skip_io.odb 2_floorplan.sdc |
218 | | - log_cmd place_pins \ |
219 | | - -hor_layers $::env(IO_PLACER_H) \ |
220 | | - -ver_layers $::env(IO_PLACER_V) \ |
221 | | - {*}[env_var_or_empty PLACE_PINS_ARGS] |
222 | | - write_db $::env(RESULTS_DIR)/3_2_place_iop.odb |
223 | | - write_pin_placement $::env(RESULTS_DIR)/3_2_place_iop.tcl |
224 | | -} else { |
225 | | - log_cmd exec cp $::env(RESULTS_DIR)/3_1_place_gp_skip_io.odb $::env(RESULTS_DIR)/3_2_place_iop.odb |
226 | | -} |
| 20 | +source $::env(SCRIPTS_DIR)/io_placement.tcl |
227 | 21 |
|
228 | 22 | # Global placement |
229 | | -utl::set_metrics_stage "globalplace__{}" |
230 | | -set_dont_use $::env(DONT_USE_CELLS) |
231 | | - |
232 | | -if { $::env(GPL_TIMING_DRIVEN) } { |
233 | | - remove_buffers |
234 | | -} |
235 | | - |
236 | | -# Do not buffer chip-level designs |
237 | | -# by default, IO ports will be buffered |
238 | | -# to not buffer IO ports, set environment variable |
239 | | -# DONT_BUFFER_PORT = 1 |
240 | | -if { ![env_var_exists_and_non_empty FOOTPRINT] } { |
241 | | - if { ![env_var_equals DONT_BUFFER_PORTS 1] } { |
242 | | - puts "Perform port buffering..." |
243 | | - buffer_ports {*}[env_var_or_empty BUFFER_PORTS_ARGS] |
244 | | - } |
245 | | -} |
246 | | - |
247 | | -set global_placement_args {} |
248 | | - |
249 | | -# Parameters for routability mode in global placement |
250 | | -append_env_var global_placement_args GPL_ROUTABILITY_DRIVEN -routability_driven 0 |
251 | | - |
252 | | -# Parameters for timing driven mode in global placement |
253 | | -if { $::env(GPL_TIMING_DRIVEN) } { |
254 | | - lappend global_placement_args {-timing_driven} |
255 | | - if { [info exists ::env(GPL_KEEP_OVERFLOW)] } { |
256 | | - lappend global_placement_args -keep_resize_below_overflow $::env(GPL_KEEP_OVERFLOW) |
257 | | - } |
258 | | -} |
259 | | - |
260 | | -proc do_placement { global_placement_args } { |
261 | | - set all_args [concat [list -density [place_density_with_lb_addon] \ |
262 | | - -pad_left $::env(CELL_PAD_IN_SITES_GLOBAL_PLACEMENT) \ |
263 | | - -pad_right $::env(CELL_PAD_IN_SITES_GLOBAL_PLACEMENT)] \ |
264 | | - $global_placement_args] |
265 | | - |
266 | | - lappend all_args {*}[env_var_or_empty GLOBAL_PLACEMENT_ARGS] |
267 | | - |
268 | | - log_cmd global_placement {*}$all_args |
269 | | -} |
270 | | - |
271 | | -set result [catch { do_placement $global_placement_args } errMsg] |
272 | | -if { $result != 0 } { |
273 | | - write_db $::env(RESULTS_DIR)/3_3_place_gp-failed.odb |
274 | | - error $errMsg |
275 | | -} |
276 | | - |
277 | | -estimate_parasitics -placement |
278 | | - |
279 | | -if { [env_var_equals CLUSTER_FLOPS 1] } { |
280 | | - cluster_flops |
281 | | - estimate_parasitics -placement |
282 | | -} |
283 | | - |
284 | | -report_metrics 3 "global place" false false |
285 | | - |
286 | | -write_db $::env(RESULTS_DIR)/3_3_place_gp.odb |
| 23 | +source $::env(SCRIPTS_DIR)/global_place.tcl |
287 | 24 |
|
288 | 25 | # Resizing |
289 | | -utl::set_metrics_stage "placeopt__{}" |
290 | | -estimate_parasitics -placement |
291 | | - |
292 | | -set instance_count_before [sta::network_leaf_instance_count] |
293 | | -set pin_count_before [sta::network_leaf_pin_count] |
294 | | - |
295 | | -set_dont_use $::env(DONT_USE_CELLS) |
296 | | - |
297 | | -if { [env_var_exists_and_non_empty EARLY_SIZING_CAP_RATIO] } { |
298 | | - log_cmd set_opt_config -set_early_sizing_cap_ratio $env(EARLY_SIZING_CAP_RATIO) |
299 | | -} |
300 | | - |
301 | | -if { [env_var_exists_and_non_empty SWAP_ARITH_OPERATORS] } { |
302 | | - replace_arith_modules |
303 | | -} |
304 | | - |
305 | | -repair_design_helper |
306 | | - |
307 | | -# hold violations are not repaired until after CTS |
308 | | - |
309 | | -# post report |
310 | | - |
311 | | -puts "Floating nets: " |
312 | | -report_floating_nets |
313 | | - |
314 | | -report_metrics 3 "resizer" true false |
315 | | - |
316 | | -puts "Instance count before $instance_count_before, after [sta::network_leaf_instance_count]" |
317 | | -puts "Pin count before $pin_count_before, after [sta::network_leaf_pin_count]" |
318 | | - |
319 | | -write_db $::env(RESULTS_DIR)/3_4_place_resized.odb |
| 26 | +source $::env(SCRIPTS_DIR)/resize.tcl |
320 | 27 |
|
321 | 28 | # Detailed placement |
322 | | -utl::set_metrics_stage "detailedplace__{}" |
323 | | - |
324 | | -proc do_dpl { } { |
325 | | - # Only for use with hybrid rows |
326 | | - if { [env_var_equals BALANCE_ROWS 1] } { |
327 | | - balance_row_usage |
328 | | - } |
329 | | - |
330 | | - set_placement_padding -global \ |
331 | | - -left $::env(CELL_PAD_IN_SITES_DETAIL_PLACEMENT) \ |
332 | | - -right $::env(CELL_PAD_IN_SITES_DETAIL_PLACEMENT) |
333 | | - detailed_placement |
334 | | - |
335 | | - if { [env_var_equals ENABLE_DPO 1] } { |
336 | | - if { [env_var_exists_and_non_empty DPO_MAX_DISPLACEMENT] } { |
337 | | - improve_placement -max_displacement $::env(DPO_MAX_DISPLACEMENT) |
338 | | - } else { |
339 | | - improve_placement |
340 | | - } |
341 | | - } |
342 | | - optimize_mirroring |
343 | | - |
344 | | - utl::info FLW 12 "Placement violations [check_placement -verbose]." |
345 | | - |
346 | | - estimate_parasitics -placement |
347 | | -} |
348 | | - |
349 | | -set result [catch { do_dpl } errMsg] |
350 | | -if { $result != 0 } { |
351 | | - write_db $::env(RESULTS_DIR)/3_5_place_dp-failed.odb |
352 | | - error $errMsg |
353 | | -} |
354 | | - |
355 | | -report_metrics 3 "detailed place" true false |
356 | | - |
357 | | -write_db $::env(RESULTS_DIR)/3_5_place_dp.odb |
| 29 | +source $::env(SCRIPTS_DIR)/detail_place.tcl |
358 | 30 |
|
359 | 31 | # Repair timing after placement |
360 | | -utl::set_metrics_stage "place_repair_timing__{}" |
361 | | - |
362 | | -set_placement_padding -global \ |
363 | | - -left $::env(CELL_PAD_IN_SITES_DETAIL_PLACEMENT) \ |
364 | | - -right $::env(CELL_PAD_IN_SITES_DETAIL_PLACEMENT) |
365 | | - |
366 | | -puts "Repair setup and hold violations" |
367 | | -estimate_parasitics -placement |
368 | | - |
369 | | -set additional_args_repair_timing "" |
370 | | -append_env_var additional_args_repair_timing MAX_REPAIR_TIMING_ITER -max_iterations 1 |
371 | | - |
372 | | -log_cmd repair_timing -repair_tns $::env(TNS_END_PERCENT) \ |
373 | | - {*}$additional_args_repair_timing |
374 | | - |
375 | | -# Legalize placement after timing repair |
376 | | -detailed_placement |
377 | | - |
378 | | -puts "Estimate parasitics" |
379 | | -estimate_parasitics -placement |
380 | | -report_metrics 3 "place repair timing" true false |
381 | | - |
382 | | -write_db $::env(RESULTS_DIR)/3_6_place_repair_timing.odb |
| 32 | +source $::env(SCRIPTS_DIR)/repair_timing_post_place.tcl |
0 commit comments