librelane 2.4.0.dev8__py3-none-any.whl → 3.0.0.dev22__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/__main__.py +12 -15
- librelane/common/__init__.py +1 -1
- librelane/common/drc.py +88 -7
- librelane/common/misc.py +6 -6
- librelane/common/toolbox.py +1 -1
- librelane/config/config.py +5 -1
- librelane/config/flow.py +51 -66
- librelane/config/pdk_compat.py +79 -2
- librelane/config/preprocessor.py +1 -1
- librelane/config/variable.py +2 -2
- librelane/flows/classic.py +1 -0
- librelane/flows/flow.py +3 -6
- librelane/flows/sequential.py +85 -40
- librelane/plugins.py +1 -1
- librelane/scripts/magic/common/read.tcl +2 -2
- librelane/scripts/magic/gds/extras_mag.tcl +2 -2
- librelane/scripts/odbpy/diodes.py +2 -2
- librelane/scripts/openroad/common/dpl.tcl +1 -1
- librelane/scripts/openroad/common/grt.tcl +3 -3
- librelane/scripts/openroad/common/io.tcl +163 -45
- librelane/scripts/openroad/common/resizer.tcl +1 -40
- librelane/scripts/openroad/common/set_global_connections.tcl +2 -2
- librelane/scripts/openroad/common/set_power_nets.tcl +1 -1
- librelane/scripts/openroad/common/set_rc.tcl +159 -40
- librelane/scripts/openroad/cts.tcl +37 -6
- librelane/scripts/openroad/cut_rows.tcl +19 -4
- librelane/scripts/openroad/drt.tcl +59 -8
- librelane/scripts/openroad/dump_rc.tcl +105 -0
- librelane/scripts/openroad/fill.tcl +2 -2
- librelane/scripts/openroad/floorplan.tcl +5 -3
- librelane/scripts/openroad/gpl.tcl +7 -8
- librelane/scripts/openroad/insert_buffer.tcl +2 -2
- librelane/scripts/openroad/ioplacer.tcl +1 -2
- librelane/scripts/openroad/irdrop.tcl +3 -3
- librelane/scripts/openroad/pdn.tcl +17 -18
- librelane/scripts/openroad/rcx.tcl +1 -1
- librelane/scripts/openroad/repair_design.tcl +14 -7
- librelane/scripts/openroad/repair_design_postgrt.tcl +13 -6
- librelane/scripts/openroad/rsz_timing_postcts.tcl +13 -12
- librelane/scripts/openroad/rsz_timing_postgrt.tcl +13 -12
- librelane/scripts/openroad/sta/check_macro_instances.tcl +1 -1
- librelane/scripts/openroad/tapcell.tcl +13 -6
- librelane/scripts/openroad/ungpl.tcl +23 -0
- librelane/state/__init__.py +1 -1
- librelane/state/design_format.py +194 -142
- librelane/state/state.py +20 -21
- librelane/steps/checker.py +12 -1
- librelane/steps/common_variables.py +4 -4
- librelane/steps/cvc_rv.py +1 -1
- librelane/steps/klayout.py +14 -6
- librelane/steps/magic.py +18 -2
- librelane/steps/misc.py +1 -1
- librelane/steps/odb.py +50 -31
- librelane/steps/openroad.py +455 -128
- librelane/steps/pyosys.py +20 -5
- librelane/steps/step.py +17 -20
- librelane/steps/tclstep.py +9 -7
- librelane/steps/yosys.py +1 -1
- {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/METADATA +1 -1
- {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/RECORD +62 -60
- {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/WHEEL +0 -0
- {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/entry_points.txt +0 -0
librelane/flows/sequential.py
CHANGED
|
@@ -26,6 +26,7 @@ from typing import (
|
|
|
26
26
|
Union,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
+
from deprecated.sphinx import deprecated
|
|
29
30
|
from rapidfuzz import process, fuzz, utils
|
|
30
31
|
|
|
31
32
|
from .flow import Flow, FlowException, FlowError
|
|
@@ -40,6 +41,10 @@ from ..steps import (
|
|
|
40
41
|
)
|
|
41
42
|
|
|
42
43
|
Substitution = Union[str, Type[Step], None]
|
|
44
|
+
SubstitutionsObject = Union[
|
|
45
|
+
Dict[str, Substitution],
|
|
46
|
+
List[Tuple[str, Substitution]],
|
|
47
|
+
]
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
class SequentialFlow(Flow):
|
|
@@ -69,20 +74,53 @@ class SequentialFlow(Flow):
|
|
|
69
74
|
:cvar gating_config_vars: A mapping from step ID (wildcards) to lists of
|
|
70
75
|
Boolean variable names. All Boolean variables must be True for a step with
|
|
71
76
|
a specific ID to execute.
|
|
77
|
+
|
|
78
|
+
:cvar Substitutions: Consumed by the subclass initializer - allows for a
|
|
79
|
+
quick interface where steps can be removed, replaced, appended or
|
|
80
|
+
prepended. After subclass intialization, it is set to ``None``, and
|
|
81
|
+
a new subclass must be created to modify substitutions further.
|
|
82
|
+
|
|
83
|
+
The list of substitutions may be specified as either a dictionary
|
|
84
|
+
or a list of tuples: while the former is more terse, the latter is
|
|
85
|
+
allows using the same key more than once.
|
|
86
|
+
|
|
87
|
+
The substitutions are mappings from Step IDs or objects to Step IDs,
|
|
88
|
+
objects, or ``None``. In case of ``None``, the step in question is
|
|
89
|
+
removed.
|
|
90
|
+
|
|
91
|
+
In case the key is specified as a string, you may add ``-`` as a prefix
|
|
92
|
+
to the Step ID to indicate you want to insert a step before the step
|
|
93
|
+
in question, and similary ``+`` indicates you want to insert a step
|
|
94
|
+
after the step in question. You may not prepend or append ``None``.
|
|
95
|
+
|
|
96
|
+
Step IDs are made unique after every substitution, i.e., whenever the
|
|
97
|
+
substitution occurs, the first instance of a Step in a sequential flow
|
|
98
|
+
shall have its ID unadulterated, while the next instance will have
|
|
99
|
+
``-1``, the one after ``-2``, etc. If ``-1`` is removed, the previous
|
|
100
|
+
``-2`` shall become ``-1``, for example.
|
|
72
101
|
"""
|
|
73
102
|
|
|
74
|
-
Substitutions: Optional[
|
|
103
|
+
Substitutions: Optional[SubstitutionsObject] = None
|
|
75
104
|
gating_config_vars: Dict[str, List[str]] = {}
|
|
76
105
|
|
|
106
|
+
def __init__(
|
|
107
|
+
self,
|
|
108
|
+
*args,
|
|
109
|
+
**kwargs,
|
|
110
|
+
):
|
|
111
|
+
self.Steps = self.Steps.copy() # Break global reference
|
|
112
|
+
super().__init__(*args, **kwargs)
|
|
113
|
+
|
|
114
|
+
# ---
|
|
115
|
+
|
|
77
116
|
def __init_subclass__(Self, scm_type=None, name=None, **kwargs):
|
|
78
117
|
Self.Steps = Self.Steps.copy() # Break global reference
|
|
79
118
|
Self.config_vars = Self.config_vars.copy()
|
|
80
119
|
Self.gating_config_vars = Self.gating_config_vars.copy()
|
|
81
|
-
if substitute := Self.Substitutions:
|
|
82
|
-
for key, item in substitute.items():
|
|
83
|
-
Self.__substitute_step(Self, key, item)
|
|
84
|
-
|
|
85
120
|
Self.__normalize_step_ids(Self)
|
|
121
|
+
if Self.Substitutions:
|
|
122
|
+
Self.__substitute_in_place(Self, Self.Substitutions)
|
|
123
|
+
Self.Substitutions = None
|
|
86
124
|
|
|
87
125
|
# Validate Gating Config Vars
|
|
88
126
|
variables_by_name = {}
|
|
@@ -108,7 +146,7 @@ class SequentialFlow(Flow):
|
|
|
108
146
|
)
|
|
109
147
|
|
|
110
148
|
@classmethod
|
|
111
|
-
def
|
|
149
|
+
def Make(Self, step_ids: List[str]) -> Type[SequentialFlow]:
|
|
112
150
|
Step_list = []
|
|
113
151
|
for name in step_ids:
|
|
114
152
|
step = Step.factory.get(name)
|
|
@@ -123,9 +161,16 @@ class SequentialFlow(Flow):
|
|
|
123
161
|
return CustomSequentialFlow
|
|
124
162
|
|
|
125
163
|
@classmethod
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
164
|
+
@deprecated(
|
|
165
|
+
"use .Make",
|
|
166
|
+
version="3.0.0",
|
|
167
|
+
action="once",
|
|
168
|
+
)
|
|
169
|
+
def make(Self, step_ids: List[str]) -> Type[SequentialFlow]:
|
|
170
|
+
return Self.Make(step_ids)
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def Substitute(Self, Substitutions: SubstitutionsObject) -> Type[SequentialFlow]:
|
|
129
174
|
"""
|
|
130
175
|
Convenience method to quickly subclass a sequential flow and add
|
|
131
176
|
Substitutions to it.
|
|
@@ -136,20 +181,19 @@ class SequentialFlow(Flow):
|
|
|
136
181
|
"""
|
|
137
182
|
return type(Self.__name__ + "'", (Self,), {"Substitutions": Substitutions})
|
|
138
183
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
**kwargs,
|
|
184
|
+
@staticmethod
|
|
185
|
+
def __substitute_in_place(
|
|
186
|
+
target: Type[SequentialFlow],
|
|
187
|
+
Substitutions: Optional[SubstitutionsObject],
|
|
144
188
|
):
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if
|
|
148
|
-
for key, item in
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
189
|
+
if Substitutions is None:
|
|
190
|
+
return Substitutions
|
|
191
|
+
if isinstance(Substitutions, dict):
|
|
192
|
+
for key, item in Substitutions.items():
|
|
193
|
+
target.__substitute_step(target, key, item)
|
|
194
|
+
else:
|
|
195
|
+
for key, item in Substitutions:
|
|
196
|
+
target.__substitute_step(target, key, item)
|
|
153
197
|
|
|
154
198
|
@staticmethod
|
|
155
199
|
def __substitute_step(
|
|
@@ -189,23 +233,23 @@ class SequentialFlow(Flow):
|
|
|
189
233
|
if with_step is None:
|
|
190
234
|
for index in reversed(step_indices):
|
|
191
235
|
del target.Steps[index]
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
with_step = with_step_opt
|
|
236
|
+
else:
|
|
237
|
+
if isinstance(with_step, str):
|
|
238
|
+
with_step_opt = Step.factory.get(with_step)
|
|
239
|
+
if with_step_opt is None:
|
|
240
|
+
raise FlowException(
|
|
241
|
+
f"Could not {mode} '{id}' with '{with_step}': no replacement step with ID '{with_step}' found."
|
|
242
|
+
)
|
|
243
|
+
with_step = with_step_opt
|
|
201
244
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
245
|
+
for i in step_indices:
|
|
246
|
+
if mode == "replace":
|
|
247
|
+
target.Steps[i] = with_step
|
|
248
|
+
elif mode == "append":
|
|
249
|
+
target.Steps.insert(i + 1, with_step)
|
|
250
|
+
elif mode == "prepend":
|
|
251
|
+
target.Steps.insert(i, with_step)
|
|
252
|
+
target.__normalize_step_ids(target)
|
|
209
253
|
|
|
210
254
|
@staticmethod
|
|
211
255
|
def __normalize_step_ids(target: Union[SequentialFlow, Type[SequentialFlow]]):
|
|
@@ -213,14 +257,15 @@ class SequentialFlow(Flow):
|
|
|
213
257
|
|
|
214
258
|
for i, step in enumerate(target.Steps):
|
|
215
259
|
counter = 0
|
|
216
|
-
|
|
260
|
+
imp_id = step.get_implementation_id()
|
|
261
|
+
id = imp_id
|
|
217
262
|
if (
|
|
218
263
|
id == NotImplemented
|
|
219
264
|
): # Will be validated later by initialization: ignore for now
|
|
220
265
|
continue
|
|
221
266
|
while id in ids_used:
|
|
222
267
|
counter += 1
|
|
223
|
-
id = f"{
|
|
268
|
+
id = f"{imp_id}-{counter}"
|
|
224
269
|
if id != step.id:
|
|
225
270
|
target.Steps[i] = step.with_id(id)
|
|
226
271
|
ids_used.add(id)
|
librelane/plugins.py
CHANGED
|
@@ -55,8 +55,8 @@ proc read_extra_gds {} {
|
|
|
55
55
|
set old_readonly [gds readonly]
|
|
56
56
|
gds rescale false
|
|
57
57
|
gds readonly true
|
|
58
|
-
if { [info exist ::env(
|
|
59
|
-
set gds_files_in $::env(
|
|
58
|
+
if { [info exist ::env(EXTRA_GDS)] } {
|
|
59
|
+
set gds_files_in $::env(EXTRA_GDS)
|
|
60
60
|
foreach gds_file $gds_files_in {
|
|
61
61
|
puts "> gds read $gds_file"
|
|
62
62
|
gds read $gds_file
|
|
@@ -25,8 +25,8 @@ if { $::env(MAGIC_GDS_POLYGON_SUBCELLS) } {
|
|
|
25
25
|
gds polygon subcells true
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
if {
|
|
29
|
-
set gds_files_in $::env(
|
|
28
|
+
if { [info exist ::env(EXTRA_GDS)] } {
|
|
29
|
+
set gds_files_in $::env(EXTRA_GDS)
|
|
30
30
|
foreach gds_file $gds_files_in {
|
|
31
31
|
gds read $gds_file
|
|
32
32
|
|
|
@@ -330,8 +330,8 @@ class DiodeInserter:
|
|
|
330
330
|
"--threshold",
|
|
331
331
|
"threshold_microns",
|
|
332
332
|
type=Decimal,
|
|
333
|
-
|
|
334
|
-
help="Minimum Manhattan distance of a net to be considered an antenna risk requiring a diode.
|
|
333
|
+
required=True,
|
|
334
|
+
help="Minimum Manhattan distance of a net to be considered an antenna risk requiring a diode.",
|
|
335
335
|
)
|
|
336
336
|
@click_odb
|
|
337
337
|
def place(
|
|
@@ -15,7 +15,7 @@ source $::env(SCRIPTS_DIR)/openroad/common/dpl_cell_pad.tcl
|
|
|
15
15
|
|
|
16
16
|
remove_fillers
|
|
17
17
|
|
|
18
|
-
detailed_placement\
|
|
18
|
+
log_cmd detailed_placement\
|
|
19
19
|
-max_displacement [subst { $::env(PL_MAX_DISPLACEMENT_X) $::env(PL_MAX_DISPLACEMENT_Y) }]
|
|
20
20
|
|
|
21
21
|
if { [info exists ::env(PL_OPTIMIZE_MIRRORING)] && $::env(PL_OPTIMIZE_MIRRORING) } {
|
|
@@ -26,7 +26,7 @@ lappend arg_list -verbose
|
|
|
26
26
|
if { $::env(GRT_ALLOW_CONGESTION) == 1 } {
|
|
27
27
|
lappend arg_list -allow_congestion
|
|
28
28
|
}
|
|
29
|
-
puts $arg_list
|
|
30
|
-
global_route {*}$arg_list
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
log_cmd global_route {*}$arg_list
|
|
31
|
+
|
|
32
|
+
write_guide $::env(STEP_DIR)/after_grt.guide
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2022-
|
|
1
|
+
# Copyright 2022-2025 Efabless Corporation
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -125,14 +125,14 @@ proc read_current_netlist {args} {
|
|
|
125
125
|
flags {-powered}
|
|
126
126
|
|
|
127
127
|
if { [info exists flags(-powered)] } {
|
|
128
|
-
puts "Reading top-level powered netlist at '$::env(
|
|
129
|
-
if {[catch {read_verilog $::env(
|
|
128
|
+
puts "Reading top-level powered netlist at '$::env(CURRENT_PNL)'…"
|
|
129
|
+
if {[catch {read_verilog $::env(CURRENT_PNL)} errmsg]} {
|
|
130
130
|
puts stderr $errmsg
|
|
131
131
|
exit 1
|
|
132
132
|
}
|
|
133
133
|
} else {
|
|
134
|
-
puts "Reading top-level netlist at '$::env(
|
|
135
|
-
if {[catch {read_verilog $::env(
|
|
134
|
+
puts "Reading top-level netlist at '$::env(CURRENT_NL)'…"
|
|
135
|
+
if {[catch {read_verilog $::env(CURRENT_NL)} errmsg]} {
|
|
136
136
|
puts stderr $errmsg
|
|
137
137
|
exit 1
|
|
138
138
|
}
|
|
@@ -153,7 +153,7 @@ proc read_timing_info {args} {
|
|
|
153
153
|
return
|
|
154
154
|
}
|
|
155
155
|
set corner_name $::env(_CURRENT_CORNER_NAME)
|
|
156
|
-
define_corners $corner_name
|
|
156
|
+
log_cm define_corners $corner_name
|
|
157
157
|
|
|
158
158
|
puts "Reading timing models for corner $corner_name…"
|
|
159
159
|
|
|
@@ -240,31 +240,35 @@ proc read_spefs {} {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
proc read_pnr_libs {args} {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
243
|
+
set i "0"
|
|
244
|
+
set tc_key "_LIB_CORNER_$i"
|
|
245
|
+
set corner_names [list]
|
|
246
|
+
while { [info exists ::env($tc_key)] } {
|
|
247
|
+
set corner_name [lindex $::env($tc_key) 0]
|
|
248
|
+
set corner_libs [lreplace $::env($tc_key) 0 0]
|
|
249
|
+
set corner($corner_name) $corner_libs
|
|
250
|
+
incr i
|
|
251
|
+
set tc_key "_LIB_CORNER_$i"
|
|
252
|
+
lappend corner_names $corner_name
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
define_corners {*}[array name corner]
|
|
256
|
+
|
|
257
|
+
foreach corner_name [array name corner] {
|
|
258
|
+
puts "Reading timing models for corner $corner_name…"
|
|
259
|
+
|
|
260
|
+
set corner_models $corner($corner_name)
|
|
261
|
+
foreach model $corner_models {
|
|
262
|
+
puts "Reading timing library for the '$corner_name' corner at '$model'…"
|
|
263
|
+
read_liberty -corner $corner_name $model
|
|
262
264
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
|
|
266
|
+
if { [info exists ::env(EXTRA_LIBS) ] } {
|
|
267
|
+
puts "Reading explicitly-specified extra libs for $corner_name…"
|
|
268
|
+
foreach extra_lib $::env(EXTRA_LIBS) {
|
|
269
|
+
puts "Reading extra timing library for the '$corner_name' corner at '$extra_lib'…"
|
|
270
|
+
read_liberty -corner $corner_name $extra_lib
|
|
271
|
+
}
|
|
268
272
|
}
|
|
269
273
|
}
|
|
270
274
|
}
|
|
@@ -302,6 +306,7 @@ proc read_current_odb {args} {
|
|
|
302
306
|
keys {}\
|
|
303
307
|
flags {}
|
|
304
308
|
|
|
309
|
+
read_pnr_libs
|
|
305
310
|
puts "Reading OpenROAD database at '$::env(CURRENT_ODB)'…"
|
|
306
311
|
if { [ catch {read_db $::env(CURRENT_ODB)} errmsg ]} {
|
|
307
312
|
puts stderr $errmsg
|
|
@@ -311,7 +316,6 @@ proc read_current_odb {args} {
|
|
|
311
316
|
set_global_vars
|
|
312
317
|
|
|
313
318
|
# Read supporting views (if applicable)
|
|
314
|
-
read_pnr_libs
|
|
315
319
|
read_current_sdc
|
|
316
320
|
set_dont_use_cells
|
|
317
321
|
}
|
|
@@ -402,32 +406,32 @@ proc write_views {args} {
|
|
|
402
406
|
write_db $::env(SAVE_ODB)
|
|
403
407
|
}
|
|
404
408
|
|
|
405
|
-
if { [info exists ::env(
|
|
406
|
-
puts "Writing netlist to '$::env(
|
|
407
|
-
write_verilog $::env(
|
|
409
|
+
if { [info exists ::env(SAVE_NL)] } {
|
|
410
|
+
puts "Writing netlist to '$::env(SAVE_NL)'…"
|
|
411
|
+
write_verilog $::env(SAVE_NL)
|
|
408
412
|
}
|
|
409
413
|
|
|
410
|
-
if { [info exists ::env(
|
|
411
|
-
puts "Writing powered netlist to '$::env(
|
|
412
|
-
write_verilog -include_pwr_gnd $::env(
|
|
414
|
+
if { [info exists ::env(SAVE_PNL)] } {
|
|
415
|
+
puts "Writing powered netlist to '$::env(SAVE_PNL)'…"
|
|
416
|
+
write_verilog -include_pwr_gnd $::env(SAVE_PNL)
|
|
413
417
|
}
|
|
414
418
|
|
|
415
|
-
if { [info exists ::env(
|
|
419
|
+
if { [info exists ::env(SAVE_SDF_PNL)] } {
|
|
416
420
|
set exclude_cells "[get_timing_excluded_cells]"
|
|
417
|
-
puts "Writing nofill powered netlist to '$::env(
|
|
421
|
+
puts "Writing nofill powered netlist to '$::env(SAVE_SDF_PNL)'…"
|
|
418
422
|
puts "Excluding $exclude_cells"
|
|
419
423
|
write_verilog -include_pwr_gnd \
|
|
420
|
-
-remove_cells "
|
|
421
|
-
$::env(
|
|
424
|
+
-remove_cells "[get_timing_excluded_cells]"\
|
|
425
|
+
$::env(SAVE_SDF_PNL)
|
|
422
426
|
}
|
|
423
427
|
|
|
424
|
-
if { [info exists ::env(
|
|
428
|
+
if { [info exists ::env(SAVE_LOGICAL_PNL)] } {
|
|
425
429
|
set exclude_cells "[get_physical_cells]"
|
|
426
|
-
puts "Writing nofilldiode powered netlist to '$::env(
|
|
430
|
+
puts "Writing nofilldiode powered netlist to '$::env(SAVE_LOGICAL_PNL)'…"
|
|
427
431
|
puts "Excluding $exclude_cells"
|
|
428
432
|
write_verilog -include_pwr_gnd \
|
|
429
|
-
-remove_cells "
|
|
430
|
-
$::env(
|
|
433
|
+
-remove_cells "[get_physical_cells]"\
|
|
434
|
+
$::env(SAVE_LOGICAL_PNL)
|
|
431
435
|
}
|
|
432
436
|
|
|
433
437
|
if { [info exists ::env(SAVE_OPENROAD_LEF)] } {
|
|
@@ -538,3 +542,117 @@ if { [namespace exists utl] } {
|
|
|
538
542
|
puts "%OL_METRIC $metric $value"
|
|
539
543
|
}
|
|
540
544
|
}
|
|
545
|
+
|
|
546
|
+
proc exit_unless_gui {{status 0}} {
|
|
547
|
+
if { ![info exists ::env(_OPENROAD_GUI)] || !$::env(_OPENROAD_GUI) } {
|
|
548
|
+
exit $status
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
proc find_unfixed_macros {} {
|
|
553
|
+
set macros [list]
|
|
554
|
+
|
|
555
|
+
foreach inst [$::block getInsts] {
|
|
556
|
+
set inst_master [$inst getMaster]
|
|
557
|
+
|
|
558
|
+
# BLOCK means MACRO cells
|
|
559
|
+
if { ![string match [$inst_master getType] "BLOCK"] } {
|
|
560
|
+
continue
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if { [$inst isFixed] } {
|
|
564
|
+
continue
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
lappend macros $inst
|
|
568
|
+
}
|
|
569
|
+
return $macros
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
proc get_layers {args} {
|
|
573
|
+
sta::parse_key_args "get_layers" args \
|
|
574
|
+
keys {-types -map}\
|
|
575
|
+
flags {-constrained}
|
|
576
|
+
|
|
577
|
+
if { ![info exists keys(-types)] } {
|
|
578
|
+
puts "\[ERROR\] Invalid usage of get_layers: -types is required."
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
set layers [$::tech getLayers]
|
|
582
|
+
set result [list]
|
|
583
|
+
set adding [expr ![info exists flags(-constrained)]]
|
|
584
|
+
foreach layer $layers {
|
|
585
|
+
set name [$layer getName]
|
|
586
|
+
if {"$::env(RT_MIN_LAYER)" == "$name"} {
|
|
587
|
+
set adding 1
|
|
588
|
+
}
|
|
589
|
+
if { [lsearch $keys(-types) [$layer getType]] != -1 && $adding} {
|
|
590
|
+
lappend result $layer
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if {"$::env(RT_MAX_LAYER)" == "$name"} {
|
|
594
|
+
set adding [info exists flags(-constrained)]
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
}
|
|
598
|
+
if { [info exists keys(-map)] } {
|
|
599
|
+
set result [lmap layer $result "\$layer $keys(-map)"]
|
|
600
|
+
}
|
|
601
|
+
return $result
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
proc append_if_exists_argument {list_arg glob_variable_name option} {
|
|
605
|
+
upvar $list_arg local_array
|
|
606
|
+
if [info exists ::env($glob_variable_name) ] {
|
|
607
|
+
lappend local_array $option $::env($glob_variable_name)
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
proc append_if_flag {list_arg glob_variable_name flag} {
|
|
612
|
+
upvar $list_arg local_array
|
|
613
|
+
if { [info exists ::env($glob_variable_name)] && $::env($glob_variable_name) } {
|
|
614
|
+
lappend local_array $flag
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
proc append_if_not_flag {list_arg glob_variable_name flag} {
|
|
618
|
+
upvar $list_arg local_array
|
|
619
|
+
if { [info exists ::env($glob_variable_name)] && !$::env($glob_variable_name) } {
|
|
620
|
+
lappend local_array $flag
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
# Code below adapted from OpenROAD Flow Scripts under the following license:
|
|
625
|
+
#
|
|
626
|
+
# BSD 3-Clause License
|
|
627
|
+
#
|
|
628
|
+
# Copyright (c) 2018-2023, The Regents of the University of California
|
|
629
|
+
# All rights reserved.
|
|
630
|
+
#
|
|
631
|
+
# Redistribution and use in source and binary forms, with or without
|
|
632
|
+
# modification, are permitted provided that the following conditions are met:
|
|
633
|
+
|
|
634
|
+
# * Redistributions of source code must retain the above copyright notice, this
|
|
635
|
+
# list of conditions and the following disclaimer.
|
|
636
|
+
#
|
|
637
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
638
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
639
|
+
# and/or other materials provided with the distribution.
|
|
640
|
+
#
|
|
641
|
+
# * Neither the name of the copyright holder nor the names of its
|
|
642
|
+
# contributors may be used to endorse or promote products derived from
|
|
643
|
+
# this software without specific prior written permission.
|
|
644
|
+
#
|
|
645
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
646
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
647
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
648
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
649
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
650
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
651
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
652
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
653
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
654
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
655
|
+
proc log_cmd {cmd args} {
|
|
656
|
+
puts "+ $cmd [join $args " "]"
|
|
657
|
+
return [$cmd {*}$args]
|
|
658
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2022-
|
|
1
|
+
# Copyright 2022-2024 Efabless Corporation
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -11,45 +11,6 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
proc load_rsz_corners {args} {
|
|
15
|
-
set i "0"
|
|
16
|
-
set tc_key "RSZ_CORNER_$i"
|
|
17
|
-
while { [info exists ::env($tc_key)] } {
|
|
18
|
-
set corner_name [lindex $::env($tc_key) 0]
|
|
19
|
-
set corner_libs [lreplace $::env($tc_key) 0 0]
|
|
20
|
-
|
|
21
|
-
set corner($corner_name) $corner_libs
|
|
22
|
-
|
|
23
|
-
incr i
|
|
24
|
-
set tc_key "RSZ_CORNER_$i"
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if { $i == "0" } {
|
|
28
|
-
puts stderr "\[WARNING\] No resizer-specific timing information read."
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
define_corners {*}[array name corner]
|
|
33
|
-
|
|
34
|
-
foreach corner_name [array name corner] {
|
|
35
|
-
puts "Reading timing models for corner $corner_name…"
|
|
36
|
-
|
|
37
|
-
set corner_models $corner($corner_name)
|
|
38
|
-
foreach model $corner_models {
|
|
39
|
-
puts "Reading timing library for the '$corner_name' corner at '$model'…"
|
|
40
|
-
read_liberty -corner $corner_name $model
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if { [info exists ::env(EXTRA_LIBS) ] } {
|
|
44
|
-
puts "Reading explicitly-specified extra libs for $corner_name…"
|
|
45
|
-
foreach extra_lib $::env(EXTRA_LIBS) {
|
|
46
|
-
puts "Reading extra timing library for the '$corner_name' corner at '$extra_lib'…"
|
|
47
|
-
read_liberty -corner $corner_name $extra_lib
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
14
|
proc set_dont_touch_objects {args} {
|
|
54
15
|
set rx $::env(RSZ_DONT_TOUCH_RX)
|
|
55
16
|
if { $rx != {^$} } {
|
|
@@ -45,7 +45,7 @@ proc set_global_connections {} {
|
|
|
45
45
|
|
|
46
46
|
if { $power_pin == "" || $ground_pin == "" } {
|
|
47
47
|
puts "PDN_MACRO_CONNECTIONS missing power and ground pin names"
|
|
48
|
-
|
|
48
|
+
exit_unless_gui 1
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
set matched 0
|
|
@@ -57,7 +57,7 @@ proc set_global_connections {} {
|
|
|
57
57
|
}
|
|
58
58
|
if { $matched != 1 } {
|
|
59
59
|
puts "\[ERROR\] No match found for regular expression '$instance_name' defined in PDN_MACRO_CONNECTIONS."
|
|
60
|
-
|
|
60
|
+
exit_unless_gui 1
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
add_global_connection \
|
|
@@ -17,7 +17,7 @@ if { [info exists ::env(VDD_NETS)] || [info exists ::env(GND_NETS)] } {
|
|
|
17
17
|
# current assumption: they cannot have a common ground
|
|
18
18
|
if { ! [info exists ::env(VDD_NETS)] || ! [info exists ::env(GND_NETS)] } {
|
|
19
19
|
puts stderr "\[ERROR\] VDD_NETS and GND_NETS must *both* either be defined or undefined"
|
|
20
|
-
|
|
20
|
+
exit_unless_gui 1
|
|
21
21
|
}
|
|
22
22
|
set ::env(VDD_NET) [lindex $::env(VDD_NETS) 0]
|
|
23
23
|
set ::env(GND_NET) [lindex $::env(GND_NETS) 0]
|