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.

Files changed (170) hide show
  1. librelane/__init__.py +38 -0
  2. librelane/__main__.py +479 -0
  3. librelane/__version__.py +43 -0
  4. librelane/common/__init__.py +63 -0
  5. librelane/common/cli.py +75 -0
  6. librelane/common/drc.py +246 -0
  7. librelane/common/generic_dict.py +319 -0
  8. librelane/common/metrics/__init__.py +35 -0
  9. librelane/common/metrics/__main__.py +413 -0
  10. librelane/common/metrics/library.py +354 -0
  11. librelane/common/metrics/metric.py +186 -0
  12. librelane/common/metrics/util.py +279 -0
  13. librelane/common/misc.py +456 -0
  14. librelane/common/ring_buffer.py +63 -0
  15. librelane/common/tcl.py +80 -0
  16. librelane/common/toolbox.py +549 -0
  17. librelane/common/tpe.py +41 -0
  18. librelane/common/types.py +116 -0
  19. librelane/config/__init__.py +32 -0
  20. librelane/config/__main__.py +155 -0
  21. librelane/config/config.py +1025 -0
  22. librelane/config/flow.py +490 -0
  23. librelane/config/pdk_compat.py +255 -0
  24. librelane/config/preprocessor.py +464 -0
  25. librelane/config/removals.py +45 -0
  26. librelane/config/variable.py +743 -0
  27. librelane/container.py +285 -0
  28. librelane/env_info.py +320 -0
  29. librelane/examples/spm/config.yaml +33 -0
  30. librelane/examples/spm/pin_order.cfg +14 -0
  31. librelane/examples/spm/src/impl.sdc +73 -0
  32. librelane/examples/spm/src/signoff.sdc +68 -0
  33. librelane/examples/spm/src/spm.v +73 -0
  34. librelane/examples/spm/verify/spm_tb.v +106 -0
  35. librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
  36. librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
  37. librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
  38. librelane/examples/spm-user_project_wrapper/config.json +13 -0
  39. librelane/examples/spm-user_project_wrapper/defines.v +66 -0
  40. librelane/examples/spm-user_project_wrapper/template.def +7656 -0
  41. librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
  42. librelane/flows/__init__.py +24 -0
  43. librelane/flows/builtins.py +18 -0
  44. librelane/flows/classic.py +327 -0
  45. librelane/flows/cli.py +463 -0
  46. librelane/flows/flow.py +1049 -0
  47. librelane/flows/misc.py +71 -0
  48. librelane/flows/optimizing.py +179 -0
  49. librelane/flows/sequential.py +367 -0
  50. librelane/flows/synth_explore.py +173 -0
  51. librelane/help/__main__.py +39 -0
  52. librelane/logging/__init__.py +40 -0
  53. librelane/logging/logger.py +323 -0
  54. librelane/open_pdks_rev +1 -0
  55. librelane/plugins.py +21 -0
  56. librelane/py.typed +0 -0
  57. librelane/scripts/base.sdc +80 -0
  58. librelane/scripts/klayout/Readme.md +2 -0
  59. librelane/scripts/klayout/open_design.py +63 -0
  60. librelane/scripts/klayout/render.py +121 -0
  61. librelane/scripts/klayout/stream_out.py +176 -0
  62. librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
  63. librelane/scripts/klayout/xor.drc +120 -0
  64. librelane/scripts/magic/Readme.md +1 -0
  65. librelane/scripts/magic/common/read.tcl +114 -0
  66. librelane/scripts/magic/def/antenna_check.tcl +35 -0
  67. librelane/scripts/magic/def/mag.tcl +19 -0
  68. librelane/scripts/magic/def/mag_gds.tcl +79 -0
  69. librelane/scripts/magic/drc.tcl +78 -0
  70. librelane/scripts/magic/extract_spice.tcl +98 -0
  71. librelane/scripts/magic/gds/drc_batch.tcl +74 -0
  72. librelane/scripts/magic/gds/erase_box.tcl +32 -0
  73. librelane/scripts/magic/gds/extras_mag.tcl +45 -0
  74. librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
  75. librelane/scripts/magic/get_bbox.tcl +11 -0
  76. librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
  77. librelane/scripts/magic/lef/maglef.tcl +26 -0
  78. librelane/scripts/magic/lef.tcl +57 -0
  79. librelane/scripts/magic/open.tcl +28 -0
  80. librelane/scripts/magic/wrapper.tcl +21 -0
  81. librelane/scripts/netgen/setup.tcl +28 -0
  82. librelane/scripts/odbpy/apply_def_template.py +49 -0
  83. librelane/scripts/odbpy/cell_frequency.py +107 -0
  84. librelane/scripts/odbpy/check_antenna_properties.py +116 -0
  85. librelane/scripts/odbpy/contextualize.py +109 -0
  86. librelane/scripts/odbpy/defutil.py +573 -0
  87. librelane/scripts/odbpy/diodes.py +373 -0
  88. librelane/scripts/odbpy/disconnected_pins.py +305 -0
  89. librelane/scripts/odbpy/eco_buffer.py +181 -0
  90. librelane/scripts/odbpy/eco_diode.py +139 -0
  91. librelane/scripts/odbpy/filter_unannotated.py +100 -0
  92. librelane/scripts/odbpy/io_place.py +482 -0
  93. librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
  94. librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
  95. librelane/scripts/odbpy/label_macro_pins.py +277 -0
  96. librelane/scripts/odbpy/lefutil.py +97 -0
  97. librelane/scripts/odbpy/placers.py +162 -0
  98. librelane/scripts/odbpy/power_utils.py +397 -0
  99. librelane/scripts/odbpy/random_place.py +57 -0
  100. librelane/scripts/odbpy/reader.py +250 -0
  101. librelane/scripts/odbpy/remove_buffers.py +173 -0
  102. librelane/scripts/odbpy/snap_to_grid.py +57 -0
  103. librelane/scripts/odbpy/wire_lengths.py +93 -0
  104. librelane/scripts/openroad/antenna_check.tcl +20 -0
  105. librelane/scripts/openroad/antenna_repair.tcl +31 -0
  106. librelane/scripts/openroad/basic_mp.tcl +24 -0
  107. librelane/scripts/openroad/buffer_list.tcl +10 -0
  108. librelane/scripts/openroad/common/dpl.tcl +24 -0
  109. librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
  110. librelane/scripts/openroad/common/grt.tcl +32 -0
  111. librelane/scripts/openroad/common/io.tcl +540 -0
  112. librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
  113. librelane/scripts/openroad/common/resizer.tcl +103 -0
  114. librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
  115. librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
  116. librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
  117. librelane/scripts/openroad/common/set_rc.tcl +75 -0
  118. librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
  119. librelane/scripts/openroad/cts.tcl +80 -0
  120. librelane/scripts/openroad/cut_rows.tcl +24 -0
  121. librelane/scripts/openroad/dpl.tcl +24 -0
  122. librelane/scripts/openroad/drt.tcl +37 -0
  123. librelane/scripts/openroad/fill.tcl +30 -0
  124. librelane/scripts/openroad/floorplan.tcl +145 -0
  125. librelane/scripts/openroad/gpl.tcl +88 -0
  126. librelane/scripts/openroad/grt.tcl +30 -0
  127. librelane/scripts/openroad/gui.tcl +37 -0
  128. librelane/scripts/openroad/insert_buffer.tcl +127 -0
  129. librelane/scripts/openroad/ioplacer.tcl +67 -0
  130. librelane/scripts/openroad/irdrop.tcl +51 -0
  131. librelane/scripts/openroad/pdn.tcl +52 -0
  132. librelane/scripts/openroad/rcx.tcl +32 -0
  133. librelane/scripts/openroad/repair_design.tcl +70 -0
  134. librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
  135. librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
  136. librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
  137. librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
  138. librelane/scripts/openroad/sta/corner.tcl +393 -0
  139. librelane/scripts/openroad/tapcell.tcl +25 -0
  140. librelane/scripts/openroad/write_views.tcl +27 -0
  141. librelane/scripts/pyosys/construct_abc_script.py +177 -0
  142. librelane/scripts/pyosys/json_header.py +84 -0
  143. librelane/scripts/pyosys/synthesize.py +493 -0
  144. librelane/scripts/pyosys/ys_common.py +153 -0
  145. librelane/scripts/tclsh/hello.tcl +1 -0
  146. librelane/state/__init__.py +24 -0
  147. librelane/state/__main__.py +61 -0
  148. librelane/state/design_format.py +195 -0
  149. librelane/state/state.py +359 -0
  150. librelane/steps/__init__.py +61 -0
  151. librelane/steps/__main__.py +510 -0
  152. librelane/steps/checker.py +637 -0
  153. librelane/steps/common_variables.py +340 -0
  154. librelane/steps/cvc_rv.py +169 -0
  155. librelane/steps/klayout.py +509 -0
  156. librelane/steps/magic.py +576 -0
  157. librelane/steps/misc.py +160 -0
  158. librelane/steps/netgen.py +253 -0
  159. librelane/steps/odb.py +1088 -0
  160. librelane/steps/openroad.py +2460 -0
  161. librelane/steps/openroad_alerts.py +102 -0
  162. librelane/steps/pyosys.py +640 -0
  163. librelane/steps/step.py +1571 -0
  164. librelane/steps/tclstep.py +288 -0
  165. librelane/steps/verilator.py +222 -0
  166. librelane/steps/yosys.py +371 -0
  167. librelane-2.4.0.dist-info/METADATA +169 -0
  168. librelane-2.4.0.dist-info/RECORD +170 -0
  169. librelane-2.4.0.dist-info/WHEEL +4 -0
  170. 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)"