librelane 2.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of librelane might be problematic. Click here for more details.
- librelane/__init__.py +38 -0
- librelane/__main__.py +479 -0
- librelane/__version__.py +43 -0
- librelane/common/__init__.py +63 -0
- librelane/common/cli.py +75 -0
- librelane/common/drc.py +246 -0
- librelane/common/generic_dict.py +319 -0
- librelane/common/metrics/__init__.py +35 -0
- librelane/common/metrics/__main__.py +413 -0
- librelane/common/metrics/library.py +354 -0
- librelane/common/metrics/metric.py +186 -0
- librelane/common/metrics/util.py +279 -0
- librelane/common/misc.py +456 -0
- librelane/common/ring_buffer.py +63 -0
- librelane/common/tcl.py +80 -0
- librelane/common/toolbox.py +549 -0
- librelane/common/tpe.py +41 -0
- librelane/common/types.py +116 -0
- librelane/config/__init__.py +32 -0
- librelane/config/__main__.py +155 -0
- librelane/config/config.py +1025 -0
- librelane/config/flow.py +490 -0
- librelane/config/pdk_compat.py +255 -0
- librelane/config/preprocessor.py +464 -0
- librelane/config/removals.py +45 -0
- librelane/config/variable.py +743 -0
- librelane/container.py +285 -0
- librelane/env_info.py +320 -0
- librelane/examples/spm/config.yaml +33 -0
- librelane/examples/spm/pin_order.cfg +14 -0
- librelane/examples/spm/src/impl.sdc +73 -0
- librelane/examples/spm/src/signoff.sdc +68 -0
- librelane/examples/spm/src/spm.v +73 -0
- librelane/examples/spm/verify/spm_tb.v +106 -0
- librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
- librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
- librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
- librelane/examples/spm-user_project_wrapper/config.json +13 -0
- librelane/examples/spm-user_project_wrapper/defines.v +66 -0
- librelane/examples/spm-user_project_wrapper/template.def +7656 -0
- librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
- librelane/flows/__init__.py +24 -0
- librelane/flows/builtins.py +18 -0
- librelane/flows/classic.py +327 -0
- librelane/flows/cli.py +463 -0
- librelane/flows/flow.py +1049 -0
- librelane/flows/misc.py +71 -0
- librelane/flows/optimizing.py +179 -0
- librelane/flows/sequential.py +367 -0
- librelane/flows/synth_explore.py +173 -0
- librelane/help/__main__.py +39 -0
- librelane/logging/__init__.py +40 -0
- librelane/logging/logger.py +323 -0
- librelane/open_pdks_rev +1 -0
- librelane/plugins.py +21 -0
- librelane/py.typed +0 -0
- librelane/scripts/base.sdc +80 -0
- librelane/scripts/klayout/Readme.md +2 -0
- librelane/scripts/klayout/open_design.py +63 -0
- librelane/scripts/klayout/render.py +121 -0
- librelane/scripts/klayout/stream_out.py +176 -0
- librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
- librelane/scripts/klayout/xor.drc +120 -0
- librelane/scripts/magic/Readme.md +1 -0
- librelane/scripts/magic/common/read.tcl +114 -0
- librelane/scripts/magic/def/antenna_check.tcl +35 -0
- librelane/scripts/magic/def/mag.tcl +19 -0
- librelane/scripts/magic/def/mag_gds.tcl +79 -0
- librelane/scripts/magic/drc.tcl +78 -0
- librelane/scripts/magic/extract_spice.tcl +98 -0
- librelane/scripts/magic/gds/drc_batch.tcl +74 -0
- librelane/scripts/magic/gds/erase_box.tcl +32 -0
- librelane/scripts/magic/gds/extras_mag.tcl +45 -0
- librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
- librelane/scripts/magic/get_bbox.tcl +11 -0
- librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
- librelane/scripts/magic/lef/maglef.tcl +26 -0
- librelane/scripts/magic/lef.tcl +57 -0
- librelane/scripts/magic/open.tcl +28 -0
- librelane/scripts/magic/wrapper.tcl +21 -0
- librelane/scripts/netgen/setup.tcl +28 -0
- librelane/scripts/odbpy/apply_def_template.py +49 -0
- librelane/scripts/odbpy/cell_frequency.py +107 -0
- librelane/scripts/odbpy/check_antenna_properties.py +116 -0
- librelane/scripts/odbpy/contextualize.py +109 -0
- librelane/scripts/odbpy/defutil.py +573 -0
- librelane/scripts/odbpy/diodes.py +373 -0
- librelane/scripts/odbpy/disconnected_pins.py +305 -0
- librelane/scripts/odbpy/eco_buffer.py +181 -0
- librelane/scripts/odbpy/eco_diode.py +139 -0
- librelane/scripts/odbpy/filter_unannotated.py +100 -0
- librelane/scripts/odbpy/io_place.py +482 -0
- librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
- librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
- librelane/scripts/odbpy/label_macro_pins.py +277 -0
- librelane/scripts/odbpy/lefutil.py +97 -0
- librelane/scripts/odbpy/placers.py +162 -0
- librelane/scripts/odbpy/power_utils.py +397 -0
- librelane/scripts/odbpy/random_place.py +57 -0
- librelane/scripts/odbpy/reader.py +250 -0
- librelane/scripts/odbpy/remove_buffers.py +173 -0
- librelane/scripts/odbpy/snap_to_grid.py +57 -0
- librelane/scripts/odbpy/wire_lengths.py +93 -0
- librelane/scripts/openroad/antenna_check.tcl +20 -0
- librelane/scripts/openroad/antenna_repair.tcl +31 -0
- librelane/scripts/openroad/basic_mp.tcl +24 -0
- librelane/scripts/openroad/buffer_list.tcl +10 -0
- librelane/scripts/openroad/common/dpl.tcl +24 -0
- librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
- librelane/scripts/openroad/common/grt.tcl +32 -0
- librelane/scripts/openroad/common/io.tcl +540 -0
- librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
- librelane/scripts/openroad/common/resizer.tcl +103 -0
- librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
- librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
- librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
- librelane/scripts/openroad/common/set_rc.tcl +75 -0
- librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
- librelane/scripts/openroad/cts.tcl +80 -0
- librelane/scripts/openroad/cut_rows.tcl +24 -0
- librelane/scripts/openroad/dpl.tcl +24 -0
- librelane/scripts/openroad/drt.tcl +37 -0
- librelane/scripts/openroad/fill.tcl +30 -0
- librelane/scripts/openroad/floorplan.tcl +145 -0
- librelane/scripts/openroad/gpl.tcl +88 -0
- librelane/scripts/openroad/grt.tcl +30 -0
- librelane/scripts/openroad/gui.tcl +37 -0
- librelane/scripts/openroad/insert_buffer.tcl +127 -0
- librelane/scripts/openroad/ioplacer.tcl +67 -0
- librelane/scripts/openroad/irdrop.tcl +51 -0
- librelane/scripts/openroad/pdn.tcl +52 -0
- librelane/scripts/openroad/rcx.tcl +32 -0
- librelane/scripts/openroad/repair_design.tcl +70 -0
- librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
- librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
- librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
- librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
- librelane/scripts/openroad/sta/corner.tcl +393 -0
- librelane/scripts/openroad/tapcell.tcl +25 -0
- librelane/scripts/openroad/write_views.tcl +27 -0
- librelane/scripts/pyosys/construct_abc_script.py +177 -0
- librelane/scripts/pyosys/json_header.py +84 -0
- librelane/scripts/pyosys/synthesize.py +493 -0
- librelane/scripts/pyosys/ys_common.py +153 -0
- librelane/scripts/tclsh/hello.tcl +1 -0
- librelane/state/__init__.py +24 -0
- librelane/state/__main__.py +61 -0
- librelane/state/design_format.py +195 -0
- librelane/state/state.py +359 -0
- librelane/steps/__init__.py +61 -0
- librelane/steps/__main__.py +510 -0
- librelane/steps/checker.py +637 -0
- librelane/steps/common_variables.py +340 -0
- librelane/steps/cvc_rv.py +169 -0
- librelane/steps/klayout.py +509 -0
- librelane/steps/magic.py +576 -0
- librelane/steps/misc.py +160 -0
- librelane/steps/netgen.py +253 -0
- librelane/steps/odb.py +1088 -0
- librelane/steps/openroad.py +2460 -0
- librelane/steps/openroad_alerts.py +102 -0
- librelane/steps/pyosys.py +640 -0
- librelane/steps/step.py +1571 -0
- librelane/steps/tclstep.py +288 -0
- librelane/steps/verilator.py +222 -0
- librelane/steps/yosys.py +371 -0
- librelane-2.4.0.dist-info/METADATA +169 -0
- librelane-2.4.0.dist-info/RECORD +170 -0
- librelane-2.4.0.dist-info/WHEEL +4 -0
- librelane-2.4.0.dist-info/entry_points.txt +9 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# Copyright 2022-2024 Efabless Corporation
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
source $::env(_TCL_ENV_IN)
|
|
15
|
+
source $::env(SCRIPTS_DIR)/openroad/common/set_global_connections.tcl
|
|
16
|
+
|
|
17
|
+
proc string_in_file {file_path substring} {
|
|
18
|
+
set f [open $file_path r]
|
|
19
|
+
set data [read $f]
|
|
20
|
+
close $f
|
|
21
|
+
|
|
22
|
+
if { [string first $substring $data] != -1} {
|
|
23
|
+
return 1
|
|
24
|
+
}
|
|
25
|
+
return 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
proc env_var_used {file var} {
|
|
29
|
+
return [string_in_file $file "\$::env($var)"]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
proc set_global_vars {} {
|
|
33
|
+
if { [namespace exists ::ord] } {
|
|
34
|
+
set ::db [::ord::get_db]
|
|
35
|
+
set ::chip [$::db getChip]
|
|
36
|
+
set ::tech [$::db getTech]
|
|
37
|
+
set ::block [$::chip getBlock]
|
|
38
|
+
set ::dbu [$::tech getDbUnitsPerMicron]
|
|
39
|
+
set ::libs [$::db getLibs]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
proc read_current_sdc {} {
|
|
44
|
+
if { ![info exists ::env(_SDC_IN)]} {
|
|
45
|
+
puts "\[INFO\] _SDC_IN not found. Not reading an SDC file."
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Compatibility Layer for Deprecated Variables That May Still Be Used By
|
|
50
|
+
# User Files
|
|
51
|
+
set ::env(IO_PCT) [expr $::env(IO_DELAY_CONSTRAINT) / 100]
|
|
52
|
+
set ::env(SYNTH_TIMING_DERATE) [expr $::env(TIME_DERATING_CONSTRAINT) / 100]
|
|
53
|
+
set ::env(SYNTH_MAX_FANOUT) $::env(MAX_FANOUT_CONSTRAINT)
|
|
54
|
+
set ::env(SYNTH_CLOCK_UNCERTAINTY) $::env(CLOCK_UNCERTAINTY_CONSTRAINT)
|
|
55
|
+
set ::env(SYNTH_CLOCK_TRANSITION) $::env(CLOCK_TRANSITION_CONSTRAINT)
|
|
56
|
+
set ::env(SYNTH_CAP_LOAD) $::env(OUTPUT_CAP_LOAD)
|
|
57
|
+
if { [info exists ::env(MAX_TRANSITION_CONSTRAINT)] } {
|
|
58
|
+
set ::env(SYNTH_MAX_TRAN) $::env(MAX_TRANSITION_CONSTRAINT)
|
|
59
|
+
}
|
|
60
|
+
if { [env_var_used $::env(_SDC_IN) SYNTH_DRIVING_CELL_PIN] == 1 } {
|
|
61
|
+
set synth_driving_cell_bk $::env(SYNTH_DRIVING_CELL)
|
|
62
|
+
set ::env(SYNTH_DRIVING_CELL_PIN) [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 1]
|
|
63
|
+
set ::env(SYNTH_DRIVING_CELL) [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 0]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
puts "Reading design constraints file at '$::env(_SDC_IN)'…"
|
|
67
|
+
if {[catch {read_sdc $::env(_SDC_IN)} errmsg]} {
|
|
68
|
+
puts stderr $errmsg
|
|
69
|
+
exit 1
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if { ![string_in_file $::env(_SDC_IN) "set_propagated_clock"] && ![string_in_file $::env(_SDC_IN) "unset_propagated_clock"] } {
|
|
73
|
+
if { [info exists ::env(OPENLANE_SDC_IDEAL_CLOCKS)] && $::env(OPENLANE_SDC_IDEAL_CLOCKS) } {
|
|
74
|
+
puts "\[INFO\] No information on clock propagation in input SDC file-- unpropagating all clocks."
|
|
75
|
+
unset_propagated_clock [all_clocks]
|
|
76
|
+
} else {
|
|
77
|
+
puts "\[INFO\] No information on clock propagation in input SDC file-- propagating all clocks."
|
|
78
|
+
set_propagated_clock [all_clocks]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Restore Environment
|
|
83
|
+
unset ::env(IO_PCT)
|
|
84
|
+
unset ::env(SYNTH_TIMING_DERATE)
|
|
85
|
+
unset ::env(SYNTH_MAX_FANOUT)
|
|
86
|
+
unset ::env(SYNTH_CLOCK_UNCERTAINTY)
|
|
87
|
+
unset ::env(SYNTH_CLOCK_TRANSITION)
|
|
88
|
+
unset ::env(SYNTH_CAP_LOAD)
|
|
89
|
+
if { [info exists ::env(SYNTH_MAX_TRAN)] } {
|
|
90
|
+
unset ::env(SYNTH_MAX_TRAN)
|
|
91
|
+
}
|
|
92
|
+
if { [info exists ::env(SYNTH_DRIVING_CELL_PIN)] } {
|
|
93
|
+
unset ::env(SYNTH_DRIVING_CELL_PIN)
|
|
94
|
+
set ::env(SYNTH_DRIVING_CELL) $synth_driving_cell_bk
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
proc read_pdn_cfg {} {
|
|
99
|
+
|
|
100
|
+
# Compatibility Layer for Deprecated Variables That May Still Be Used By
|
|
101
|
+
# User Files
|
|
102
|
+
set ::env(DESIGN_IS_CORE) $::env(FP_PDN_MULTILAYER)
|
|
103
|
+
set ::env(FP_PDN_ENABLE_MACROS_GRID) $::env(PDN_CONNECT_MACROS_TO_GRID)
|
|
104
|
+
set ::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_RAIL_LAYER)
|
|
105
|
+
set ::env(FP_PDN_UPPER_LAYER) $::env(FP_PDN_HORIZONTAL_LAYER)
|
|
106
|
+
set ::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_VERTICAL_LAYER)
|
|
107
|
+
|
|
108
|
+
if {[catch {source $::env(FP_PDN_CFG)} errmsg]} {
|
|
109
|
+
puts stderr $errmsg
|
|
110
|
+
exit 1
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Restore Environment
|
|
114
|
+
unset ::env(DESIGN_IS_CORE)
|
|
115
|
+
unset ::env(FP_PDN_ENABLE_MACROS_GRID)
|
|
116
|
+
unset ::env(FP_PDN_RAILS_LAYER)
|
|
117
|
+
unset ::env(FP_PDN_UPPER_LAYER)
|
|
118
|
+
unset ::env(FP_PDN_LOWER_LAYER)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
proc read_current_netlist {args} {
|
|
123
|
+
sta::parse_key_args "read_current_netlist" args \
|
|
124
|
+
keys {}\
|
|
125
|
+
flags {-powered}
|
|
126
|
+
|
|
127
|
+
if { [info exists flags(-powered)] } {
|
|
128
|
+
puts "Reading top-level powered netlist at '$::env(CURRENT_POWERED_NETLIST)'…"
|
|
129
|
+
if {[catch {read_verilog $::env(CURRENT_POWERED_NETLIST)} errmsg]} {
|
|
130
|
+
puts stderr $errmsg
|
|
131
|
+
exit 1
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
puts "Reading top-level netlist at '$::env(CURRENT_NETLIST)'…"
|
|
135
|
+
if {[catch {read_verilog $::env(CURRENT_NETLIST)} errmsg]} {
|
|
136
|
+
puts stderr $errmsg
|
|
137
|
+
exit 1
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
puts "Linking design '$::env(DESIGN_NAME)' from netlist…"
|
|
142
|
+
link_design $::env(DESIGN_NAME)
|
|
143
|
+
set_global_vars
|
|
144
|
+
read_current_sdc
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
proc read_timing_info {args} {
|
|
148
|
+
sta::parse_key_args "read_timing_info" args \
|
|
149
|
+
keys {}\
|
|
150
|
+
flags {-powered}
|
|
151
|
+
|
|
152
|
+
if { ![info exists ::env(_CURRENT_CORNER_NAME)] } {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
set corner_name $::env(_CURRENT_CORNER_NAME)
|
|
156
|
+
define_corners $corner_name
|
|
157
|
+
|
|
158
|
+
puts "Reading timing models for corner $corner_name…"
|
|
159
|
+
|
|
160
|
+
foreach lib $::env(_CURRENT_CORNER_LIBS) {
|
|
161
|
+
puts "Reading cell library for the '$corner_name' corner at '$lib'…"
|
|
162
|
+
read_liberty -corner $corner_name $lib
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if { [info exists ::env(EXTRA_LIBS) ] } {
|
|
166
|
+
puts "Reading explicitly-specified extra libs for $corner_name…"
|
|
167
|
+
foreach extra_lib $::env(EXTRA_LIBS) {
|
|
168
|
+
puts "Reading extra timing library for the '$corner_name' corner at '$extra_lib'…"
|
|
169
|
+
read_liberty -corner $corner_name $extra_lib
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
set blackbox_wildcard {/// sta-blackbox}
|
|
174
|
+
foreach nl $::env(_CURRENT_CORNER_NETLISTS) {
|
|
175
|
+
puts "Reading macro netlist at '$nl'…"
|
|
176
|
+
if { [catch {read_verilog $nl} err] } {
|
|
177
|
+
puts "Error while reading macro netlist '$nl':"
|
|
178
|
+
puts $err
|
|
179
|
+
puts "Make sure that this a gate-level netlist and not an RTL file."
|
|
180
|
+
exit 1
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if { [info exists ::env(EXTRA_VERILOG_MODELS)] } {
|
|
184
|
+
foreach verilog_file $::env(EXTRA_VERILOG_MODELS) {
|
|
185
|
+
if { [string_in_file $verilog_file $blackbox_wildcard] } {
|
|
186
|
+
puts "Found '$blackbox_wildcard' in '$verilog_file', skipping…"
|
|
187
|
+
} elseif { [catch {puts "Reading Verilog model at '$verilog_file'…"; read_verilog $verilog_file} err] } {
|
|
188
|
+
puts "Error while reading $verilog_file:"
|
|
189
|
+
puts $err
|
|
190
|
+
puts "Make sure that this a gate-level netlist and not an RTL file, otherwise, you can add the following comment '$blackbox_wildcard' in the file to skip it and blackbox the modules inside if needed."
|
|
191
|
+
exit 1
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if { [info exists flags(-powered)] } {
|
|
196
|
+
read_current_netlist -powered
|
|
197
|
+
} else {
|
|
198
|
+
read_current_netlist
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
proc lshift {inputlist} {
|
|
203
|
+
upvar $inputlist argv
|
|
204
|
+
set arg [lindex $argv 0]
|
|
205
|
+
#set argv [lrange $argv 1 end] ;# below is much faster - lreplace can make use of unshared Tcl_Obj to avoid alloc'ing the result
|
|
206
|
+
set argv [lreplace $argv[set argv {}] 0 0]
|
|
207
|
+
return $arg
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
proc read_spefs {} {
|
|
211
|
+
if { [info exists ::env(_CURRENT_SPEF_BY_CORNER)] } {
|
|
212
|
+
set corner_name $::env(_CURRENT_CORNER_NAME)
|
|
213
|
+
puts "Reading top-level design parasitics for the '$corner_name' corner at '$::env(_CURRENT_SPEF_BY_CORNER)'…"
|
|
214
|
+
read_spef -corner $corner_name $::env(_CURRENT_SPEF_BY_CORNER)
|
|
215
|
+
}
|
|
216
|
+
if { [info exists ::env(_CURRENT_CORNER_SPEFS)] } {
|
|
217
|
+
set corner_name $::env(_CURRENT_CORNER_NAME)
|
|
218
|
+
foreach spefs $::env(_CURRENT_CORNER_SPEFS) {
|
|
219
|
+
set instance_path [lshift spefs]
|
|
220
|
+
foreach spef $spefs {
|
|
221
|
+
puts "Reading '$instance_path' parasitics for the '$corner_name' corner at '$spef'…"
|
|
222
|
+
read_spef -corner $corner_name -path $instance_path $spef
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if { [info exists ::env(_CURRENT_CORNER_EXTRA_SPEFS_BACKCOMPAT)] } {
|
|
227
|
+
set corner_name $::env(_CURRENT_CORNER_NAME)
|
|
228
|
+
foreach pair $::env(_CURRENT_CORNER_EXTRA_SPEFS_BACKCOMPAT) {
|
|
229
|
+
set module_name [lindex $pair 0]
|
|
230
|
+
set spef [lindex $pair 1]
|
|
231
|
+
foreach cell [get_cells * -hierarchical] {
|
|
232
|
+
if { "[get_property $cell ref_name]" eq "$module_name"} {
|
|
233
|
+
set instance_path [get_property $cell full_name]
|
|
234
|
+
puts "Reading '$instance_path' parasitics for the '$corner_name' corner at '$spef'…"
|
|
235
|
+
read_spef -corner $corner_name -path $instance_path $spef
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
proc read_pnr_libs {args} {
|
|
243
|
+
# _PNR_LIBS contains all libs and extra libs but with known-bad cells
|
|
244
|
+
# excluded, so OpenROAD can use cells by functionality and come up
|
|
245
|
+
# with a valid design.
|
|
246
|
+
|
|
247
|
+
# If there are ANY libs already read- just leave
|
|
248
|
+
if { [get_libs -quiet *] != {} } {
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
define_corners $::env(DEFAULT_CORNER)
|
|
253
|
+
|
|
254
|
+
foreach lib $::env(_PNR_LIBS) {
|
|
255
|
+
puts "Reading library file at '$lib'…"
|
|
256
|
+
read_liberty $lib
|
|
257
|
+
}
|
|
258
|
+
if { [info exists ::env(_MACRO_LIBS) ] } {
|
|
259
|
+
foreach macro_lib $::env(_MACRO_LIBS) {
|
|
260
|
+
puts "Reading macro library file at '$macro_lib'…"
|
|
261
|
+
read_liberty $macro_lib
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if { [info exists ::env(EXTRA_LIBS) ] } {
|
|
265
|
+
foreach extra_lib $::env(EXTRA_LIBS) {
|
|
266
|
+
puts "Reading extra library file at '$extra_lib'…"
|
|
267
|
+
read_liberty $extra_lib
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
proc read_lefs {{tlef_key "TECH_LEF"}} {
|
|
273
|
+
set tlef $::env($tlef_key)
|
|
274
|
+
|
|
275
|
+
puts "Reading technology LEF file at '$tlef'…"
|
|
276
|
+
read_lef $tlef
|
|
277
|
+
|
|
278
|
+
foreach lef $::env(CELL_LEFS) {
|
|
279
|
+
puts "Reading cell LEF file at '$lef'…"
|
|
280
|
+
read_lef $lef
|
|
281
|
+
}
|
|
282
|
+
if { [info exist ::env(MACRO_LEFS)] } {
|
|
283
|
+
foreach lef $::env(MACRO_LEFS) {
|
|
284
|
+
puts "Reading macro LEF file at '$lef'…"
|
|
285
|
+
read_lef $lef
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if { [info exist ::env(EXTRA_LEFS)] } {
|
|
289
|
+
foreach lef $::env(EXTRA_LEFS) {
|
|
290
|
+
puts "Reading extra LEF file at '$lef'…"
|
|
291
|
+
read_lef $lef
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
proc set_dont_use_cells {} {
|
|
297
|
+
set_dont_use $::env(_PNR_EXCLUDED_CELLS)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
proc read_current_odb {args} {
|
|
301
|
+
sta::parse_key_args "read_current_odb" args \
|
|
302
|
+
keys {}\
|
|
303
|
+
flags {}
|
|
304
|
+
|
|
305
|
+
puts "Reading OpenROAD database at '$::env(CURRENT_ODB)'…"
|
|
306
|
+
if { [ catch {read_db $::env(CURRENT_ODB)} errmsg ]} {
|
|
307
|
+
puts stderr $errmsg
|
|
308
|
+
exit 1
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
set_global_vars
|
|
312
|
+
|
|
313
|
+
# Read supporting views (if applicable)
|
|
314
|
+
read_pnr_libs
|
|
315
|
+
read_current_sdc
|
|
316
|
+
set_dont_use_cells
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
proc _populate_cells_by_class {} {
|
|
320
|
+
if { [info exists ::_cells_by_class(physical)] } {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
set ::_cells_by_class(physical) [list]
|
|
325
|
+
set ::_cells_by_class(non_timing) [list]
|
|
326
|
+
set _comment_ {
|
|
327
|
+
We naïvely assume anything not in these classes is not a cell with a
|
|
328
|
+
logical function. This may not be comprehensive, but is good enough.
|
|
329
|
+
|
|
330
|
+
CORE just means a macro used in the core area (i.e. a standard cell.)
|
|
331
|
+
|
|
332
|
+
Thing is, it has a lot of subclasses for physical cells:
|
|
333
|
+
|
|
334
|
+
`FEEDTHRU`,`SPACER`,`ANTENNACELL`,`WELLTAP`
|
|
335
|
+
|
|
336
|
+
Only `TIEHIGH`, `TIELOW` are for logical cells. Thus, the inclusion
|
|
337
|
+
list allows them as well. `BLOCKS` are macros, which we cannot discern
|
|
338
|
+
whether they have a logical function or not, so we include them
|
|
339
|
+
regardless.
|
|
340
|
+
|
|
341
|
+
We do make one exception for `ANTENNACELL`s. These are not counted as
|
|
342
|
+
logical cells but they are not exempt from the so-called SDF-friendly
|
|
343
|
+
netlist as they do affect timing ever so slightly.
|
|
344
|
+
}
|
|
345
|
+
set logical_classes {
|
|
346
|
+
BLOCK
|
|
347
|
+
BUMP
|
|
348
|
+
CORE
|
|
349
|
+
CORE_TIEHIGH
|
|
350
|
+
CORE_TIELOW
|
|
351
|
+
COVER
|
|
352
|
+
PAD
|
|
353
|
+
PAD_AREAIO
|
|
354
|
+
PAD_INOUT
|
|
355
|
+
PAD_INPUT
|
|
356
|
+
PAD_OUTPUT
|
|
357
|
+
PAD_POWER
|
|
358
|
+
PAD_SPACER
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
foreach lib $::libs {
|
|
362
|
+
foreach master [$lib getMasters] {
|
|
363
|
+
if { [lsearch -exact $logical_classes [$master getType]] == -1 } {
|
|
364
|
+
lappend ::_cells_by_class(physical) [$master getName]
|
|
365
|
+
if { "[$master getType]" != "CORE_ANTENNACELL" } {
|
|
366
|
+
lappend ::_cells_by_class(non_timing) [$master getName]
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
proc get_timing_excluded_cells {args} {
|
|
374
|
+
_populate_cells_by_class
|
|
375
|
+
return $::_cells_by_class(non_timing)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
proc get_physical_cells {args} {
|
|
379
|
+
_populate_cells_by_class
|
|
380
|
+
return $::_cells_by_class(physical)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
proc write_views {args} {
|
|
384
|
+
# This script will attempt to write views based on existing "SAVE_"
|
|
385
|
+
# environment variables. If the SAVE_ variable exists, the script will
|
|
386
|
+
# attempt to write a corresponding view to the specified location.
|
|
387
|
+
sta::parse_key_args "write_views" args \
|
|
388
|
+
keys {}\
|
|
389
|
+
flags {-no_global_connect}
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
source $::env(SCRIPTS_DIR)/openroad/common/set_power_nets.tcl
|
|
393
|
+
puts "Setting global connections for newly added cells…"
|
|
394
|
+
set_global_connections
|
|
395
|
+
|
|
396
|
+
puts "Updating metrics…"
|
|
397
|
+
report_design_area_metrics
|
|
398
|
+
report_cell_usage
|
|
399
|
+
|
|
400
|
+
if { [info exists ::env(SAVE_ODB)] } {
|
|
401
|
+
puts "Writing OpenROAD database to '$::env(SAVE_ODB)'…"
|
|
402
|
+
write_db $::env(SAVE_ODB)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if { [info exists ::env(SAVE_NETLIST)] } {
|
|
406
|
+
puts "Writing netlist to '$::env(SAVE_NETLIST)'…"
|
|
407
|
+
write_verilog $::env(SAVE_NETLIST)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if { [info exists ::env(SAVE_POWERED_NETLIST)] } {
|
|
411
|
+
puts "Writing powered netlist to '$::env(SAVE_POWERED_NETLIST)'…"
|
|
412
|
+
write_verilog -include_pwr_gnd $::env(SAVE_POWERED_NETLIST)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if { [info exists ::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)] } {
|
|
416
|
+
set exclude_cells "[get_timing_excluded_cells]"
|
|
417
|
+
puts "Writing nofill powered netlist to '$::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)'…"
|
|
418
|
+
puts "Excluding $exclude_cells"
|
|
419
|
+
write_verilog -include_pwr_gnd \
|
|
420
|
+
-remove_cells "$exclude_cells"\
|
|
421
|
+
$::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if { [info exists ::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)] } {
|
|
425
|
+
set exclude_cells "[get_physical_cells]"
|
|
426
|
+
puts "Writing nofilldiode powered netlist to '$::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)'…"
|
|
427
|
+
puts "Excluding $exclude_cells"
|
|
428
|
+
write_verilog -include_pwr_gnd \
|
|
429
|
+
-remove_cells "$exclude_cells"\
|
|
430
|
+
$::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if { [info exists ::env(SAVE_OPENROAD_LEF)] } {
|
|
434
|
+
puts "Writing LEF to '$::env(SAVE_OPENROAD_LEF)'…"
|
|
435
|
+
set arg_list [list]
|
|
436
|
+
if {$::env(OPENROAD_LEF_BLOAT_OCCUPIED_LAYERS)} {
|
|
437
|
+
lappend arg_list -bloat_occupied_layers
|
|
438
|
+
}
|
|
439
|
+
write_abstract_lef {*}$arg_list $::env(SAVE_OPENROAD_LEF)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if { [info exists ::env(SAVE_DEF)] } {
|
|
443
|
+
puts "Writing layout to '$::env(SAVE_DEF)'…"
|
|
444
|
+
write_def $::env(SAVE_DEF)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if { [info exists ::env(SAVE_SDC)] } {
|
|
448
|
+
puts "Writing timing constraints to '$::env(SAVE_SDC)'…"
|
|
449
|
+
write_sdc -no_timestamp $::env(SAVE_SDC)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if { [info exists ::env(SAVE_SPEF)] } {
|
|
453
|
+
puts "Writing extracted parasitics to '$::env(SAVE_SPEF)'…"
|
|
454
|
+
write_spef $::env(SAVE_SPEF)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if { [info exists ::env(SAVE_GUIDE)] } {
|
|
458
|
+
puts "Writing routing guides to '$::env(SAVE_GUIDE)'…"
|
|
459
|
+
write_guides $::env(SAVE_GUIDE)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if { [info exists ::env(SAVE_SDF)] } {
|
|
463
|
+
set corners [sta::corners]
|
|
464
|
+
if { [llength $corners] > 1 } {
|
|
465
|
+
} else {
|
|
466
|
+
puts "Writing SDF to '$::env(SAVE_SDF)'…"
|
|
467
|
+
write_sdf -include_typ -divider . $::env(SAVE_SDF)
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
proc write_sdfs {} {
|
|
473
|
+
if { [info exists ::env(_SDF_SAVE_DIR)] } {
|
|
474
|
+
set corners [sta::corners]
|
|
475
|
+
|
|
476
|
+
puts "Writing SDF files for all corners…"
|
|
477
|
+
foreach corner $corners {
|
|
478
|
+
set corner_name [$corner name]
|
|
479
|
+
set target $::env(_SDF_SAVE_DIR)/$::env(DESIGN_NAME)__$corner_name.sdf
|
|
480
|
+
write_sdf -include_typ -divider . -corner $corner_name $target
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
proc write_libs {} {
|
|
486
|
+
if { [info exists ::env(_LIB_SAVE_DIR)] } {
|
|
487
|
+
puts "Removing Clock latencies before writing libs…"
|
|
488
|
+
# This is to avoid OpenSTA writing a context-dependent timing model
|
|
489
|
+
set_clock_latency -source -max 0 [all_clocks]
|
|
490
|
+
set_clock_latency -source -min 0 [all_clocks]
|
|
491
|
+
set corners [sta::corners]
|
|
492
|
+
puts "Writing timing models for all corners…"
|
|
493
|
+
foreach corner $corners {
|
|
494
|
+
set corner_name [$corner name]
|
|
495
|
+
set target $::env(_LIB_SAVE_DIR)/$::env(DESIGN_NAME)__$corner_name.lib
|
|
496
|
+
puts "Writing timing models for the $corner_name corner to $target…"
|
|
497
|
+
write_timing_model -corner $corner_name $target
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
proc max {a b} {
|
|
503
|
+
if { $a > $b } {
|
|
504
|
+
return $a
|
|
505
|
+
} else {
|
|
506
|
+
return $b
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
set ::metric_count 0
|
|
511
|
+
set ::metrics_file ""
|
|
512
|
+
if { [namespace exists utl] } {
|
|
513
|
+
proc write_metric_str {metric value} {
|
|
514
|
+
puts "Writing metric $metric: $value"
|
|
515
|
+
utl::metric $metric $value
|
|
516
|
+
}
|
|
517
|
+
proc write_metric_int {metric value} {
|
|
518
|
+
puts "Writing metric $metric: $value"
|
|
519
|
+
utl::metric_int $metric $value
|
|
520
|
+
}
|
|
521
|
+
proc write_metric_num {metric value} {
|
|
522
|
+
puts "Writing metric $metric: $value"
|
|
523
|
+
utl::metric_float $metric $value
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
proc write_metric_num {metric value} {
|
|
527
|
+
if { $value == 1e30 } {
|
|
528
|
+
set value inf
|
|
529
|
+
} elseif { $value == -1e30 } {
|
|
530
|
+
set value -inf
|
|
531
|
+
}
|
|
532
|
+
puts "%OL_METRIC_F $metric $value"
|
|
533
|
+
}
|
|
534
|
+
proc write_metric_int {metric value} {
|
|
535
|
+
puts "%OL_METRIC_I $metric $value"
|
|
536
|
+
}
|
|
537
|
+
proc write_metric_str {metric value} {
|
|
538
|
+
puts "%OL_METRIC $metric $value"
|
|
539
|
+
}
|
|
540
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Copyright 2020-2022 Efabless Corporation
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
source $::env(SCRIPTS_DIR)/openroad/common/set_global_connections.tcl
|
|
16
|
+
set_global_connections
|
|
17
|
+
|
|
18
|
+
set secondary []
|
|
19
|
+
foreach vdd $::env(VDD_NETS) gnd $::env(GND_NETS) {
|
|
20
|
+
if { $vdd != $::env(VDD_NET)} {
|
|
21
|
+
lappend secondary $vdd
|
|
22
|
+
|
|
23
|
+
set db_net [[ord::get_db_block] findNet $vdd]
|
|
24
|
+
if {$db_net == "NULL"} {
|
|
25
|
+
set net [odb::dbNet_create [ord::get_db_block] $vdd]
|
|
26
|
+
$net setSpecial
|
|
27
|
+
$net setSigType "POWER"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if { $gnd != $::env(GND_NET)} {
|
|
32
|
+
lappend secondary $gnd
|
|
33
|
+
|
|
34
|
+
set db_net [[ord::get_db_block] findNet $gnd]
|
|
35
|
+
if {$db_net == "NULL"} {
|
|
36
|
+
set net [odb::dbNet_create [ord::get_db_block] $gnd]
|
|
37
|
+
$net setSpecial
|
|
38
|
+
$net setSigType "GROUND"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET) \
|
|
44
|
+
-secondary_power $secondary
|
|
45
|
+
|
|
46
|
+
if { $::env(FP_PDN_MULTILAYER) == 1 } {
|
|
47
|
+
define_pdn_grid \
|
|
48
|
+
-name stdcell_grid \
|
|
49
|
+
-starts_with POWER \
|
|
50
|
+
-voltage_domain CORE \
|
|
51
|
+
-pins "$::env(FP_PDN_VERTICAL_LAYER) $::env(FP_PDN_HORIZONTAL_LAYER)"
|
|
52
|
+
|
|
53
|
+
add_pdn_stripe \
|
|
54
|
+
-grid stdcell_grid \
|
|
55
|
+
-layer $::env(FP_PDN_VERTICAL_LAYER) \
|
|
56
|
+
-width $::env(FP_PDN_VWIDTH) \
|
|
57
|
+
-pitch $::env(FP_PDN_VPITCH) \
|
|
58
|
+
-offset $::env(FP_PDN_VOFFSET) \
|
|
59
|
+
-spacing $::env(FP_PDN_VSPACING) \
|
|
60
|
+
-starts_with POWER -extend_to_core_ring
|
|
61
|
+
|
|
62
|
+
add_pdn_stripe \
|
|
63
|
+
-grid stdcell_grid \
|
|
64
|
+
-layer $::env(FP_PDN_HORIZONTAL_LAYER) \
|
|
65
|
+
-width $::env(FP_PDN_HWIDTH) \
|
|
66
|
+
-pitch $::env(FP_PDN_HPITCH) \
|
|
67
|
+
-offset $::env(FP_PDN_HOFFSET) \
|
|
68
|
+
-spacing $::env(FP_PDN_HSPACING) \
|
|
69
|
+
-starts_with POWER -extend_to_core_ring
|
|
70
|
+
|
|
71
|
+
add_pdn_connect \
|
|
72
|
+
-grid stdcell_grid \
|
|
73
|
+
-layers "$::env(FP_PDN_VERTICAL_LAYER) $::env(FP_PDN_HORIZONTAL_LAYER)"
|
|
74
|
+
} else {
|
|
75
|
+
define_pdn_grid \
|
|
76
|
+
-name stdcell_grid \
|
|
77
|
+
-starts_with POWER \
|
|
78
|
+
-voltage_domain CORE \
|
|
79
|
+
-pins $::env(FP_PDN_VERTICAL_LAYER)
|
|
80
|
+
|
|
81
|
+
add_pdn_stripe \
|
|
82
|
+
-grid stdcell_grid \
|
|
83
|
+
-layer $::env(FP_PDN_VERTICAL_LAYER) \
|
|
84
|
+
-width $::env(FP_PDN_VWIDTH) \
|
|
85
|
+
-pitch $::env(FP_PDN_VPITCH) \
|
|
86
|
+
-offset $::env(FP_PDN_VOFFSET) \
|
|
87
|
+
-spacing $::env(FP_PDN_VSPACING) \
|
|
88
|
+
-starts_with POWER -extend_to_core_ring
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Adds the standard cell rails if enabled.
|
|
92
|
+
if { $::env(FP_PDN_ENABLE_RAILS) == 1 } {
|
|
93
|
+
add_pdn_stripe \
|
|
94
|
+
-grid stdcell_grid \
|
|
95
|
+
-layer $::env(FP_PDN_RAIL_LAYER) \
|
|
96
|
+
-width $::env(FP_PDN_RAIL_WIDTH) \
|
|
97
|
+
-followpins \
|
|
98
|
+
-starts_with POWER
|
|
99
|
+
|
|
100
|
+
add_pdn_connect \
|
|
101
|
+
-grid stdcell_grid \
|
|
102
|
+
-layers "$::env(FP_PDN_RAIL_LAYER) $::env(FP_PDN_VERTICAL_LAYER)"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Adds the core ring if enabled.
|
|
107
|
+
if { $::env(FP_PDN_CORE_RING) == 1 } {
|
|
108
|
+
if { $::env(FP_PDN_MULTILAYER) == 1 } {
|
|
109
|
+
add_pdn_ring \
|
|
110
|
+
-grid stdcell_grid \
|
|
111
|
+
-layers "$::env(FP_PDN_VERTICAL_LAYER) $::env(FP_PDN_HORIZONTAL_LAYER)" \
|
|
112
|
+
-widths "$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)" \
|
|
113
|
+
-spacings "$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)" \
|
|
114
|
+
-core_offset "$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)"
|
|
115
|
+
} else {
|
|
116
|
+
throw APPLICATION "FP_PDN_CORE_RING cannot be used when FP_PDN_MULTILAYER is set to false."
|
|
117
|
+
# add_pdn_ring \
|
|
118
|
+
# -grid stdcell_grid \
|
|
119
|
+
# -layers "$::env(FP_PDN_VERTICAL_LAYER)" \
|
|
120
|
+
# -widths "$::env(FP_PDN_CORE_RING_VWIDTH)" \
|
|
121
|
+
# -spacings "$::env(FP_PDN_CORE_RING_VSPACING)" \
|
|
122
|
+
# -core_offset "$::env(FP_PDN_CORE_RING_VOFFSET)"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
define_pdn_grid \
|
|
127
|
+
-macro \
|
|
128
|
+
-default \
|
|
129
|
+
-name macro \
|
|
130
|
+
-starts_with POWER \
|
|
131
|
+
-halo "$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)"
|
|
132
|
+
|
|
133
|
+
add_pdn_connect \
|
|
134
|
+
-grid macro \
|
|
135
|
+
-layers "$::env(FP_PDN_VERTICAL_LAYER) $::env(FP_PDN_HORIZONTAL_LAYER)"
|