librelane 3.0.0.dev23__py3-none-any.whl → 3.0.0.dev25__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/config/__main__.py +1 -4
- librelane/config/removals.py +1 -0
- librelane/config/variable.py +1 -1
- librelane/examples/spm/config.yaml +8 -8
- librelane/examples/spm-user_project_wrapper/config.json +17 -5
- librelane/scripts/odbpy/reader.py +1 -1
- librelane/scripts/openroad/common/io.tcl +38 -18
- librelane/scripts/openroad/common/pdn_cfg.tcl +38 -38
- librelane/scripts/openroad/common/set_global_connections.tcl +1 -1
- librelane/scripts/openroad/drt.tcl +3 -5
- librelane/scripts/openroad/floorplan.tcl +12 -4
- librelane/scripts/openroad/ioplacer.tcl +22 -21
- librelane/scripts/openroad/pdn.tcl +1 -1
- librelane/scripts/openroad/sta/check_macro_instances.tcl +3 -3
- librelane/scripts/openroad/sta/corner.tcl +8 -8
- librelane/scripts/pyosys/json_header.py +1 -2
- librelane/scripts/pyosys/synthesize.py +4 -4
- librelane/scripts/pyosys/ys_common.py +9 -29
- librelane/state/design_format.py +7 -0
- librelane/steps/common_variables.py +82 -33
- librelane/steps/odb.py +26 -38
- librelane/steps/openroad.py +36 -43
- librelane/steps/pyosys.py +14 -9
- librelane/steps/yosys.py +16 -6
- {librelane-3.0.0.dev23.dist-info → librelane-3.0.0.dev25.dist-info}/METADATA +1 -1
- {librelane-3.0.0.dev23.dist-info → librelane-3.0.0.dev25.dist-info}/RECORD +28 -28
- {librelane-3.0.0.dev23.dist-info → librelane-3.0.0.dev25.dist-info}/WHEEL +0 -0
- {librelane-3.0.0.dev23.dist-info → librelane-3.0.0.dev25.dist-info}/entry_points.txt +0 -0
|
@@ -50,48 +50,28 @@ def _Design_read_verilog_files(
|
|
|
50
50
|
synth_parameters: Iterable[str],
|
|
51
51
|
includes: Iterable[str],
|
|
52
52
|
defines: Iterable[str],
|
|
53
|
-
|
|
54
|
-
synlig_defer: bool = False,
|
|
53
|
+
use_slang: bool = False,
|
|
55
54
|
):
|
|
56
55
|
files = list(files) # for easier concatenation
|
|
57
56
|
include_args = [f"-I{dir}" for dir in includes]
|
|
58
57
|
define_args = [f"-D{define}" for define in defines]
|
|
59
58
|
chparams = {}
|
|
60
|
-
|
|
59
|
+
slang_chparam_args = []
|
|
61
60
|
for chparam in synth_parameters:
|
|
62
61
|
param, value = chparam.split("=", maxsplit=1) # validate
|
|
63
62
|
chparams[param] = value
|
|
64
|
-
|
|
63
|
+
slang_chparam_args.append(f"-G{param}={value}")
|
|
65
64
|
|
|
66
|
-
if
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
self.run_pass(
|
|
70
|
-
"read_systemverilog",
|
|
71
|
-
"-defer",
|
|
72
|
-
"-sverilog",
|
|
73
|
-
*define_args,
|
|
74
|
-
*include_args,
|
|
75
|
-
file,
|
|
76
|
-
)
|
|
77
|
-
self.run_pass(
|
|
78
|
-
"read_systemverilog",
|
|
79
|
-
"-link",
|
|
80
|
-
"-sverilog",
|
|
81
|
-
"-top",
|
|
82
|
-
top,
|
|
83
|
-
*synlig_chparam_args,
|
|
84
|
-
)
|
|
85
|
-
elif use_synlig:
|
|
86
|
-
self.run_pass("plugin", "-i", "synlig-sv")
|
|
65
|
+
ys.log("use_slang" if use_slang else "wtaf")
|
|
66
|
+
if use_slang:
|
|
67
|
+
self.run_pass("plugin", "-i", "slang")
|
|
87
68
|
self.run_pass(
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"-top",
|
|
69
|
+
"read_slang",
|
|
70
|
+
"--top",
|
|
91
71
|
top,
|
|
92
72
|
*define_args,
|
|
93
73
|
*include_args,
|
|
94
|
-
*
|
|
74
|
+
*slang_chparam_args,
|
|
95
75
|
*files,
|
|
96
76
|
)
|
|
97
77
|
else:
|
librelane/state/design_format.py
CHANGED
|
@@ -157,6 +157,13 @@ DesignFormat(
|
|
|
157
157
|
alts=["NETLIST"],
|
|
158
158
|
).register()
|
|
159
159
|
|
|
160
|
+
DesignFormat(
|
|
161
|
+
"logical_nl",
|
|
162
|
+
"logical_nl.v",
|
|
163
|
+
"Logical cell-only Verilog Netlist",
|
|
164
|
+
folder_override="nl",
|
|
165
|
+
).register()
|
|
166
|
+
|
|
160
167
|
DesignFormat(
|
|
161
168
|
"pnl",
|
|
162
169
|
"pnl.v",
|
|
@@ -18,204 +18,253 @@ from ..config import Variable
|
|
|
18
18
|
|
|
19
19
|
io_layer_variables = [
|
|
20
20
|
Variable(
|
|
21
|
-
"
|
|
21
|
+
"IO_PIN_V_EXTENSION",
|
|
22
22
|
Decimal,
|
|
23
23
|
"Extends the vertical io pins outside of the die by the specified units.",
|
|
24
24
|
default=0,
|
|
25
25
|
units="µm",
|
|
26
|
+
deprecated_names=["FP_IO_VEXTEND"],
|
|
26
27
|
),
|
|
27
28
|
Variable(
|
|
28
|
-
"
|
|
29
|
+
"IO_PIN_H_EXTENSION",
|
|
29
30
|
Decimal,
|
|
30
31
|
"Extends the horizontal io pins outside of the die by the specified units.",
|
|
31
32
|
default=0,
|
|
32
33
|
units="µm",
|
|
34
|
+
deprecated_names=["FP_IO_HEXTEND"],
|
|
33
35
|
),
|
|
34
36
|
Variable(
|
|
35
|
-
"
|
|
37
|
+
"IO_PIN_V_THICKNESS_MULT",
|
|
36
38
|
Decimal,
|
|
37
39
|
"A multiplier for vertical pin thickness. Base thickness is the pins layer min width.",
|
|
38
40
|
default=2,
|
|
41
|
+
deprecated_names=["FP_IO_VTHICKNESS_MULT"],
|
|
39
42
|
),
|
|
40
43
|
Variable(
|
|
41
|
-
"
|
|
44
|
+
"IO_PIN_H_THICKNESS_MULT",
|
|
42
45
|
Decimal,
|
|
43
46
|
"A multiplier for horizontal pin thickness. Base thickness is the pins layer min width.",
|
|
44
47
|
default=2,
|
|
48
|
+
deprecated_names=["FP_IO_HTHICKNESS_MULT"],
|
|
49
|
+
),
|
|
50
|
+
Variable(
|
|
51
|
+
"IO_PIN_V_LENGTH",
|
|
52
|
+
Optional[Decimal],
|
|
53
|
+
"""
|
|
54
|
+
The length of the pins with a north or south orientation. If unspecified by a PDK, OpenROAD will use whichever is higher of the following two values:
|
|
55
|
+
* The pin width
|
|
56
|
+
* The minimum value satisfying the minimum area constraint given the pin width
|
|
57
|
+
""",
|
|
58
|
+
units="µm",
|
|
59
|
+
pdk=True,
|
|
60
|
+
deprecated_names=["FP_IO_VLENGTH"],
|
|
61
|
+
),
|
|
62
|
+
Variable(
|
|
63
|
+
"IO_PIN_H_LENGTH",
|
|
64
|
+
Optional[Decimal],
|
|
65
|
+
"""
|
|
66
|
+
The length of the pins with an east or west orientation. If unspecified by a PDK, OpenROAD will use whichever is higher of the following two values:
|
|
67
|
+
* The pin width
|
|
68
|
+
* The minimum value satisfying the minimum area constraint given the pin width
|
|
69
|
+
""",
|
|
70
|
+
units="µm",
|
|
71
|
+
pdk=True,
|
|
72
|
+
deprecated_names=["FP_IO_HLENGTH"],
|
|
45
73
|
),
|
|
46
74
|
]
|
|
47
75
|
|
|
48
76
|
pdn_variables = [
|
|
49
77
|
Variable(
|
|
50
|
-
"
|
|
78
|
+
"PDN_SKIPTRIM",
|
|
51
79
|
bool,
|
|
52
80
|
"Enables `-skip_trim` option during pdngen which skips the metal trim step, which attempts to remove metal stubs.",
|
|
53
81
|
default=False,
|
|
82
|
+
deprecated_names=["FP_PDN_SKIPTRIM"],
|
|
54
83
|
),
|
|
55
84
|
Variable(
|
|
56
|
-
"
|
|
85
|
+
"PDN_CORE_RING",
|
|
57
86
|
bool,
|
|
58
87
|
"Enables adding a core ring around the design. More details on the control variables in the PDK config documentation.",
|
|
59
88
|
default=False,
|
|
89
|
+
deprecated_names=["FP_PDN_CORE_RING"],
|
|
60
90
|
),
|
|
61
91
|
Variable(
|
|
62
|
-
"
|
|
92
|
+
"PDN_ENABLE_RAILS",
|
|
63
93
|
bool,
|
|
64
94
|
"Enables the creation of rails in the power grid.",
|
|
65
95
|
default=True,
|
|
96
|
+
deprecated_names=["FP_PDN_ENABLE_RAILS"],
|
|
66
97
|
),
|
|
67
98
|
Variable(
|
|
68
|
-
"
|
|
99
|
+
"PDN_HORIZONTAL_HALO",
|
|
69
100
|
Decimal,
|
|
70
101
|
"Sets the horizontal halo around the macros during power grid insertion.",
|
|
71
102
|
default=10,
|
|
72
103
|
units="µm",
|
|
104
|
+
deprecated_names=["FP_PDN_HORIZONTAL_HALO"],
|
|
73
105
|
),
|
|
74
106
|
Variable(
|
|
75
|
-
"
|
|
107
|
+
"PDN_VERTICAL_HALO",
|
|
76
108
|
Decimal,
|
|
77
109
|
"Sets the vertical halo around the macros during power grid insertion.",
|
|
78
110
|
default=10,
|
|
79
111
|
units="µm",
|
|
112
|
+
deprecated_names=["FP_PDN_VERTICAL_HALO"],
|
|
80
113
|
),
|
|
81
114
|
Variable(
|
|
82
|
-
"
|
|
115
|
+
"PDN_MULTILAYER",
|
|
83
116
|
bool,
|
|
84
117
|
"Controls the layers used in the power grid. If set to false, only the lower layer will be used, which is useful when hardening a macro for integrating into a larger top-level design.",
|
|
85
118
|
default=True,
|
|
86
|
-
deprecated_names=["DESIGN_IS_CORE"],
|
|
119
|
+
deprecated_names=["FP_PDN_MULTILAYER", "DESIGN_IS_CORE"],
|
|
87
120
|
),
|
|
88
121
|
Variable(
|
|
89
|
-
"
|
|
122
|
+
"PDN_RAIL_OFFSET",
|
|
90
123
|
Decimal,
|
|
91
124
|
"The offset for the power distribution network rails for first metal layer.",
|
|
92
125
|
units="µm",
|
|
93
126
|
pdk=True,
|
|
127
|
+
deprecated_names=["FP_PDN_RAIL_OFFSET"],
|
|
94
128
|
),
|
|
95
129
|
Variable(
|
|
96
|
-
"
|
|
130
|
+
"PDN_VWIDTH",
|
|
97
131
|
Decimal,
|
|
98
132
|
"The strap width for the vertical layer in generated power distribution networks.",
|
|
99
133
|
units="µm",
|
|
100
134
|
pdk=True,
|
|
135
|
+
deprecated_names=["FP_PDN_VWIDTH"],
|
|
101
136
|
),
|
|
102
137
|
Variable(
|
|
103
|
-
"
|
|
138
|
+
"PDN_HWIDTH",
|
|
104
139
|
Decimal,
|
|
105
140
|
"The strap width for the horizontal layer in generated power distribution networks.",
|
|
106
141
|
units="µm",
|
|
107
142
|
pdk=True,
|
|
143
|
+
deprecated_names=["FP_PDN_HWIDTH"],
|
|
108
144
|
),
|
|
109
145
|
Variable(
|
|
110
|
-
"
|
|
146
|
+
"PDN_VSPACING",
|
|
111
147
|
Decimal,
|
|
112
148
|
"Intra-spacing (within a set) of vertical straps in generated power distribution networks.",
|
|
113
149
|
units="µm",
|
|
114
150
|
pdk=True,
|
|
151
|
+
deprecated_names=["FP_PDN_VSPACING"],
|
|
115
152
|
),
|
|
116
153
|
Variable(
|
|
117
|
-
"
|
|
154
|
+
"PDN_HSPACING",
|
|
118
155
|
Decimal,
|
|
119
156
|
"Intra-spacing (within a set) of horizontal straps in generated power distribution networks.",
|
|
120
157
|
units="µm",
|
|
121
158
|
pdk=True,
|
|
159
|
+
deprecated_names=["FP_PDN_HSPACING"],
|
|
122
160
|
),
|
|
123
161
|
Variable(
|
|
124
|
-
"
|
|
162
|
+
"PDN_VPITCH",
|
|
125
163
|
Decimal,
|
|
126
164
|
"Inter-distance (between sets) of vertical power straps in generated power distribution networks.",
|
|
127
165
|
units="µm",
|
|
128
166
|
pdk=True,
|
|
167
|
+
deprecated_names=["FP_PDN_VPITCH"],
|
|
129
168
|
),
|
|
130
169
|
Variable(
|
|
131
|
-
"
|
|
170
|
+
"PDN_HPITCH",
|
|
132
171
|
Decimal,
|
|
133
172
|
"Inter-distance (between sets) of horizontal power straps in generated power distribution networks.",
|
|
134
173
|
units="µm",
|
|
135
174
|
pdk=True,
|
|
175
|
+
deprecated_names=["FP_PDN_HPITCH"],
|
|
136
176
|
),
|
|
137
177
|
Variable(
|
|
138
|
-
"
|
|
178
|
+
"PDN_VOFFSET",
|
|
139
179
|
Decimal,
|
|
140
180
|
"Initial offset for sets of vertical power straps.",
|
|
141
181
|
units="µm",
|
|
142
182
|
pdk=True,
|
|
183
|
+
deprecated_names=["FP_PDN_VOFFSET"],
|
|
143
184
|
),
|
|
144
185
|
Variable(
|
|
145
|
-
"
|
|
186
|
+
"PDN_HOFFSET",
|
|
146
187
|
Decimal,
|
|
147
188
|
"Initial offset for sets of horizontal power straps.",
|
|
148
189
|
units="µm",
|
|
149
190
|
pdk=True,
|
|
191
|
+
deprecated_names=["FP_PDN_HOFFSET"],
|
|
150
192
|
),
|
|
151
193
|
Variable(
|
|
152
|
-
"
|
|
194
|
+
"PDN_CORE_RING_VWIDTH",
|
|
153
195
|
Decimal,
|
|
154
196
|
"The width for the vertical layer in the core ring of generated power distribution networks.",
|
|
155
197
|
units="µm",
|
|
156
198
|
pdk=True,
|
|
199
|
+
deprecated_names=["FP_PDN_CORE_RING_VWIDTH"],
|
|
157
200
|
),
|
|
158
201
|
Variable(
|
|
159
|
-
"
|
|
202
|
+
"PDN_CORE_RING_HWIDTH",
|
|
160
203
|
Decimal,
|
|
161
204
|
"The width for the horizontal layer in the core ring of generated power distribution networks.",
|
|
162
205
|
units="µm",
|
|
163
206
|
pdk=True,
|
|
207
|
+
deprecated_names=["FP_PDN_CORE_RING_HWIDTH"],
|
|
164
208
|
),
|
|
165
209
|
Variable(
|
|
166
|
-
"
|
|
210
|
+
"PDN_CORE_RING_VSPACING",
|
|
167
211
|
Decimal,
|
|
168
212
|
"The spacing for the vertical layer in the core ring of generated power distribution networks.",
|
|
169
213
|
units="µm",
|
|
170
214
|
pdk=True,
|
|
215
|
+
deprecated_names=["FP_PDN_CORE_RING_VSPACING"],
|
|
171
216
|
),
|
|
172
217
|
Variable(
|
|
173
|
-
"
|
|
218
|
+
"PDN_CORE_RING_HSPACING",
|
|
174
219
|
Decimal,
|
|
175
220
|
"The spacing for the horizontal layer in the core ring of generated power distribution networks.",
|
|
176
221
|
units="µm",
|
|
177
222
|
pdk=True,
|
|
223
|
+
deprecated_names=["FP_PDN_CORE_RING_HSPACING"],
|
|
178
224
|
),
|
|
179
225
|
Variable(
|
|
180
|
-
"
|
|
226
|
+
"PDN_CORE_RING_VOFFSET",
|
|
181
227
|
Decimal,
|
|
182
228
|
"The offset for the vertical layer in the core ring of generated power distribution networks.",
|
|
183
229
|
units="µm",
|
|
184
230
|
pdk=True,
|
|
231
|
+
deprecated_names=["FP_PDN_CORE_RING_VOFFSET"],
|
|
185
232
|
),
|
|
186
233
|
Variable(
|
|
187
|
-
"
|
|
234
|
+
"PDN_CORE_RING_HOFFSET",
|
|
188
235
|
Decimal,
|
|
189
236
|
"The offset for the horizontal layer in the core ring of generated power distribution networks.",
|
|
190
237
|
units="µm",
|
|
191
238
|
pdk=True,
|
|
239
|
+
deprecated_names=["FP_PDN_CORE_RING_HOFFSET"],
|
|
192
240
|
),
|
|
193
241
|
Variable(
|
|
194
|
-
"
|
|
242
|
+
"PDN_RAIL_LAYER",
|
|
195
243
|
str,
|
|
196
244
|
"Defines the metal layer used for PDN rails.",
|
|
197
|
-
deprecated_names=["FP_PDN_RAILS_LAYER"],
|
|
245
|
+
deprecated_names=["FP_PDN_RAIL_LAYER", "FP_PDN_RAILS_LAYER"],
|
|
198
246
|
pdk=True,
|
|
199
247
|
),
|
|
200
248
|
Variable(
|
|
201
|
-
"
|
|
249
|
+
"PDN_RAIL_WIDTH",
|
|
202
250
|
Decimal,
|
|
203
251
|
"Defines the width of PDN rails on the `FP_PDN_RAILS_LAYER` layer.",
|
|
204
252
|
units="µm",
|
|
205
253
|
pdk=True,
|
|
254
|
+
deprecated_names=["FP_PDN_RAIL_WIDTH"],
|
|
206
255
|
),
|
|
207
256
|
Variable(
|
|
208
|
-
"
|
|
257
|
+
"PDN_HORIZONTAL_LAYER",
|
|
209
258
|
str,
|
|
210
259
|
"Defines the horizontal PDN layer.",
|
|
211
|
-
deprecated_names=["FP_PDN_UPPER_LAYER"],
|
|
260
|
+
deprecated_names=["FP_PDN_HORIZONTAL_LAYER", "FP_PDN_UPPER_LAYER"],
|
|
212
261
|
pdk=True,
|
|
213
262
|
),
|
|
214
263
|
Variable(
|
|
215
|
-
"
|
|
264
|
+
"PDN_VERTICAL_LAYER",
|
|
216
265
|
str,
|
|
217
266
|
"Defines the vertical PDN layer.",
|
|
218
|
-
deprecated_names=["FP_PDN_LOWER_LAYER"],
|
|
267
|
+
deprecated_names=["FP_PDN_VERTICAL_LAYER", "FP_PDN_LOWER_LAYER"],
|
|
219
268
|
pdk=True,
|
|
220
269
|
),
|
|
221
270
|
]
|
librelane/steps/odb.py
CHANGED
|
@@ -27,7 +27,7 @@ from ..config import Instance, Macro, Variable
|
|
|
27
27
|
from ..logging import info, verbose
|
|
28
28
|
from ..state import DesignFormat, State
|
|
29
29
|
|
|
30
|
-
from .openroad import DetailedPlacement, GlobalRouting
|
|
30
|
+
from .openroad import DetailedPlacement, GlobalRouting, OpenROADStep
|
|
31
31
|
from .openroad_alerts import OpenROADAlert, OpenROADOutputProcessor
|
|
32
32
|
from .common_variables import io_layer_variables, dpl_variables, grt_variables
|
|
33
33
|
from .step import (
|
|
@@ -52,6 +52,10 @@ class OdbpyStep(Step):
|
|
|
52
52
|
|
|
53
53
|
alerts: Optional[List[OpenROADAlert]] = None
|
|
54
54
|
|
|
55
|
+
@classmethod
|
|
56
|
+
def get_openroad_path(Self) -> str:
|
|
57
|
+
return OpenROADStep.get_openroad_path()
|
|
58
|
+
|
|
55
59
|
def on_alert(self, alert: OpenROADAlert) -> OpenROADAlert:
|
|
56
60
|
if alert.code in [
|
|
57
61
|
"ORD-0039", # .openroad ignored with -python
|
|
@@ -155,7 +159,7 @@ class OdbpyStep(Step):
|
|
|
155
159
|
lefs.append(str(design_lef))
|
|
156
160
|
return (
|
|
157
161
|
[
|
|
158
|
-
|
|
162
|
+
self.get_openroad_path(),
|
|
159
163
|
"-exit",
|
|
160
164
|
"-no_splash",
|
|
161
165
|
"-metrics",
|
|
@@ -614,31 +618,10 @@ class CustomIOPlacement(OdbpyStep):
|
|
|
614
618
|
|
|
615
619
|
config_vars = io_layer_variables + [
|
|
616
620
|
Variable(
|
|
617
|
-
"
|
|
618
|
-
Optional[Decimal],
|
|
619
|
-
"""
|
|
620
|
-
The length of the pins with a north or south orientation. If unspecified by a PDK, the script will use whichever is higher of the following two values:
|
|
621
|
-
* The pin width
|
|
622
|
-
* The minimum value satisfying the minimum area constraint given the pin width
|
|
623
|
-
""",
|
|
624
|
-
units="µm",
|
|
625
|
-
pdk=True,
|
|
626
|
-
),
|
|
627
|
-
Variable(
|
|
628
|
-
"FP_IO_HLENGTH",
|
|
629
|
-
Optional[Decimal],
|
|
630
|
-
"""
|
|
631
|
-
The length of the pins with an east or west orientation. If unspecified by a PDK, the script will use whichever is higher of the following two values:
|
|
632
|
-
* The pin width
|
|
633
|
-
* The minimum value satisfying the minimum area constraint given the pin width
|
|
634
|
-
""",
|
|
635
|
-
units="µm",
|
|
636
|
-
pdk=True,
|
|
637
|
-
),
|
|
638
|
-
Variable(
|
|
639
|
-
"FP_PIN_ORDER_CFG",
|
|
621
|
+
"IO_PIN_ORDER_CFG",
|
|
640
622
|
Optional[Path],
|
|
641
|
-
"Path to
|
|
623
|
+
"Path to a custom pin configuration file.",
|
|
624
|
+
deprecated_names=["FP_PIN_ORDER_CFG"],
|
|
642
625
|
),
|
|
643
626
|
Variable(
|
|
644
627
|
"ERRORS_ON_UNMATCHED_IO",
|
|
@@ -656,28 +639,28 @@ class CustomIOPlacement(OdbpyStep):
|
|
|
656
639
|
|
|
657
640
|
def get_command(self) -> List[str]:
|
|
658
641
|
length_args = []
|
|
659
|
-
if self.config["
|
|
660
|
-
length_args += ["--ver-length", self.config["
|
|
661
|
-
if self.config["
|
|
662
|
-
length_args += ["--hor-length", self.config["
|
|
642
|
+
if self.config["IO_PIN_V_LENGTH"] is not None:
|
|
643
|
+
length_args += ["--ver-length", self.config["IO_PIN_V_LENGTH"]]
|
|
644
|
+
if self.config["IO_PIN_H_LENGTH"] is not None:
|
|
645
|
+
length_args += ["--hor-length", self.config["IO_PIN_H_LENGTH"]]
|
|
663
646
|
|
|
664
647
|
return (
|
|
665
648
|
super().get_command()
|
|
666
649
|
+ [
|
|
667
650
|
"--config",
|
|
668
|
-
self.config["
|
|
651
|
+
self.config["IO_PIN_ORDER_CFG"],
|
|
669
652
|
"--hor-layer",
|
|
670
653
|
self.config["FP_IO_HLAYER"],
|
|
671
654
|
"--ver-layer",
|
|
672
655
|
self.config["FP_IO_VLAYER"],
|
|
673
656
|
"--hor-width-mult",
|
|
674
|
-
str(self.config["
|
|
657
|
+
str(self.config["IO_PIN_V_THICKNESS_MULT"]),
|
|
675
658
|
"--ver-width-mult",
|
|
676
|
-
str(self.config["
|
|
659
|
+
str(self.config["IO_PIN_H_THICKNESS_MULT"]),
|
|
677
660
|
"--hor-extension",
|
|
678
|
-
str(self.config["
|
|
661
|
+
str(self.config["IO_PIN_H_EXTENSION"]),
|
|
679
662
|
"--ver-extension",
|
|
680
|
-
str(self.config["
|
|
663
|
+
str(self.config["IO_PIN_V_EXTENSION"]),
|
|
681
664
|
"--unmatched-error",
|
|
682
665
|
self.config["ERRORS_ON_UNMATCHED_IO"],
|
|
683
666
|
]
|
|
@@ -685,8 +668,8 @@ class CustomIOPlacement(OdbpyStep):
|
|
|
685
668
|
)
|
|
686
669
|
|
|
687
670
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
688
|
-
if self.config["
|
|
689
|
-
info(f"No custom
|
|
671
|
+
if self.config["IO_PIN_ORDER_CFG"] is None:
|
|
672
|
+
info(f"No custom I/O placement file configured, skipping '{self.id}'…")
|
|
690
673
|
return {}, {}
|
|
691
674
|
return super().run(state_in, **kwargs)
|
|
692
675
|
|
|
@@ -946,7 +929,12 @@ class CellFrequencyTables(OdbpyStep):
|
|
|
946
929
|
lib_list = self.toolbox.filter_views(self.config, self.config["LIB"])
|
|
947
930
|
env_copy["_PNR_LIBS"] = TclStep.value_to_tcl(lib_list)
|
|
948
931
|
super().run_subprocess(
|
|
949
|
-
[
|
|
932
|
+
[
|
|
933
|
+
self.get_openroad_path(),
|
|
934
|
+
"-no_splash",
|
|
935
|
+
"-exit",
|
|
936
|
+
self.get_buffer_list_script(),
|
|
937
|
+
],
|
|
950
938
|
env=env_copy,
|
|
951
939
|
log_to=self.get_buffer_list_file(),
|
|
952
940
|
)
|
librelane/steps/openroad.py
CHANGED
|
@@ -267,6 +267,10 @@ class OpenROADStep(TclStep):
|
|
|
267
267
|
),
|
|
268
268
|
]
|
|
269
269
|
|
|
270
|
+
@classmethod
|
|
271
|
+
def get_openroad_path(Self) -> str:
|
|
272
|
+
return os.getenv("_LLN_OVERRIDE_OPENROAD", "openroad")
|
|
273
|
+
|
|
270
274
|
@abstractmethod
|
|
271
275
|
def get_script_path(self) -> str:
|
|
272
276
|
pass
|
|
@@ -469,7 +473,7 @@ class OpenROADStep(TclStep):
|
|
|
469
473
|
def get_command(self) -> List[str]:
|
|
470
474
|
metrics_path = os.path.join(self.step_dir, "or_metrics_out.json")
|
|
471
475
|
return [
|
|
472
|
-
|
|
476
|
+
self.get_openroad_path(),
|
|
473
477
|
("-gui" if os.getenv("_OPENROAD_GUI", "0") == "1" else "-exit"),
|
|
474
478
|
"-no_splash",
|
|
475
479
|
"-metrics",
|
|
@@ -956,7 +960,7 @@ class STAPostPNR(STAPrePNR):
|
|
|
956
960
|
lefs.append(lef)
|
|
957
961
|
metrics_path = os.path.join(corner_dir, "filter_unannotated_metrics.json")
|
|
958
962
|
filter_unannotated_cmd = [
|
|
959
|
-
|
|
963
|
+
self.get_openroad_path(),
|
|
960
964
|
"-exit",
|
|
961
965
|
"-no_splash",
|
|
962
966
|
"-metrics",
|
|
@@ -1173,8 +1177,8 @@ class IOPlacement(OpenROADStep):
|
|
|
1173
1177
|
"""
|
|
1174
1178
|
Places I/O pins on a floor-planned ODB file using OpenROAD's built-in placer.
|
|
1175
1179
|
|
|
1176
|
-
If ``
|
|
1177
|
-
compatibility with
|
|
1180
|
+
If ``IO_PIN_ORDER_CFG`` is not ``None``, this step is skipped (for
|
|
1181
|
+
compatibility with OpenLane.)
|
|
1178
1182
|
"""
|
|
1179
1183
|
|
|
1180
1184
|
id = "OpenROAD.IOPlacement"
|
|
@@ -1185,51 +1189,31 @@ class IOPlacement(OpenROADStep):
|
|
|
1185
1189
|
+ io_layer_variables
|
|
1186
1190
|
+ [
|
|
1187
1191
|
Variable(
|
|
1188
|
-
"
|
|
1192
|
+
"IO_PIN_PLACEMENT_MODE",
|
|
1189
1193
|
Literal["matching", "random_equidistant", "annealing"],
|
|
1190
1194
|
"Decides the mode of the random IO placement option.",
|
|
1191
1195
|
default="matching",
|
|
1192
|
-
deprecated_names=[("FP_IO_MODE", _migrate_ppl_mode)],
|
|
1196
|
+
deprecated_names=[("FP_IO_MODE", _migrate_ppl_mode), "FP_PPL_MODE"],
|
|
1193
1197
|
),
|
|
1194
1198
|
Variable(
|
|
1195
|
-
"
|
|
1199
|
+
"IO_PIN_MIN_DISTANCE",
|
|
1196
1200
|
Optional[Decimal],
|
|
1197
1201
|
"The minimum distance between two pins. If unspecified by a PDK, OpenROAD will use the length of two routing tracks.",
|
|
1198
1202
|
units="µm",
|
|
1199
1203
|
pdk=True,
|
|
1204
|
+
deprecated_names=["FP_IO_MIN_DISTANCE"],
|
|
1200
1205
|
),
|
|
1201
1206
|
Variable(
|
|
1202
|
-
"
|
|
1207
|
+
"IO_PIN_ORDER_CFG",
|
|
1203
1208
|
Optional[Path],
|
|
1204
1209
|
"Path to a custom pin configuration file.",
|
|
1210
|
+
deprecated_names=["FP_PIN_ORDER_CFG"],
|
|
1205
1211
|
),
|
|
1206
1212
|
Variable(
|
|
1207
1213
|
"FP_DEF_TEMPLATE",
|
|
1208
1214
|
Optional[Path],
|
|
1209
1215
|
"Points to the DEF file to be used as a template.",
|
|
1210
1216
|
),
|
|
1211
|
-
Variable(
|
|
1212
|
-
"FP_IO_VLENGTH",
|
|
1213
|
-
Optional[Decimal],
|
|
1214
|
-
"""
|
|
1215
|
-
The length of the pins with a north or south orientation. If unspecified by a PDK, OpenROAD will use whichever is higher of the following two values:
|
|
1216
|
-
* The pin width
|
|
1217
|
-
* The minimum value satisfying the minimum area constraint given the pin width
|
|
1218
|
-
""",
|
|
1219
|
-
units="µm",
|
|
1220
|
-
pdk=True,
|
|
1221
|
-
),
|
|
1222
|
-
Variable(
|
|
1223
|
-
"FP_IO_HLENGTH",
|
|
1224
|
-
Optional[Decimal],
|
|
1225
|
-
"""
|
|
1226
|
-
The length of the pins with an east or west orientation. If unspecified by a PDK, OpenROAD will use whichever is higher of the following two values:
|
|
1227
|
-
* The pin width
|
|
1228
|
-
* The minimum value satisfying the minimum area constraint given the pin width
|
|
1229
|
-
""",
|
|
1230
|
-
units="µm",
|
|
1231
|
-
pdk=True,
|
|
1232
|
-
),
|
|
1233
1217
|
]
|
|
1234
1218
|
)
|
|
1235
1219
|
|
|
@@ -1237,8 +1221,8 @@ class IOPlacement(OpenROADStep):
|
|
|
1237
1221
|
return os.path.join(get_script_dir(), "openroad", "ioplacer.tcl")
|
|
1238
1222
|
|
|
1239
1223
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
1240
|
-
if self.config["
|
|
1241
|
-
info(f"
|
|
1224
|
+
if self.config["IO_PIN_ORDER_CFG"] is not None:
|
|
1225
|
+
info(f"IO_PIN_ORDER_CFG is set. Skipping '{self.id}'…")
|
|
1242
1226
|
return {}, {}
|
|
1243
1227
|
if self.config["FP_DEF_TEMPLATE"] is not None:
|
|
1244
1228
|
info(
|
|
@@ -1349,10 +1333,10 @@ class GeneratePDN(OpenROADStep):
|
|
|
1349
1333
|
+ pdn_variables
|
|
1350
1334
|
+ [
|
|
1351
1335
|
Variable(
|
|
1352
|
-
"
|
|
1336
|
+
"PDN_CFG",
|
|
1353
1337
|
Optional[Path],
|
|
1354
1338
|
"A custom PDN configuration file. If not provided, the default PDN config will be used.",
|
|
1355
|
-
deprecated_names=["
|
|
1339
|
+
deprecated_names=["FP_PDN_CFG"],
|
|
1356
1340
|
)
|
|
1357
1341
|
]
|
|
1358
1342
|
)
|
|
@@ -1362,17 +1346,25 @@ class GeneratePDN(OpenROADStep):
|
|
|
1362
1346
|
|
|
1363
1347
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
1364
1348
|
kwargs, env = self.extract_env(kwargs)
|
|
1365
|
-
if self.config["
|
|
1366
|
-
env["
|
|
1349
|
+
if self.config["PDN_CFG"] is None:
|
|
1350
|
+
env["PDN_CFG"] = os.path.join(
|
|
1367
1351
|
get_script_dir(), "openroad", "common", "pdn_cfg.tcl"
|
|
1368
1352
|
)
|
|
1369
|
-
info(f"'
|
|
1353
|
+
info(f"'PDN_CFG' not explicitly set, setting it to {env['PDN_CFG']}…")
|
|
1370
1354
|
views_updates, metrics_updates = super().run(state_in, env=env, **kwargs)
|
|
1371
1355
|
|
|
1356
|
+
alerts = self.alerts or []
|
|
1372
1357
|
error_reports = glob(os.path.join(self.step_dir, "*-grid-errors.rpt"))
|
|
1373
1358
|
for report in error_reports:
|
|
1374
1359
|
net = os.path.basename(report).split("-", maxsplit=1)[0]
|
|
1375
|
-
|
|
1360
|
+
no_terminals = any(
|
|
1361
|
+
alert.code == "PSM-0025" and alert.message.startswith(net)
|
|
1362
|
+
for alert in alerts
|
|
1363
|
+
)
|
|
1364
|
+
if no_terminals:
|
|
1365
|
+
count = 1
|
|
1366
|
+
else:
|
|
1367
|
+
count = get_psm_error_count(open(report, encoding="utf8"))
|
|
1376
1368
|
metrics_updates[f"design__power_grid_violation__count__net:{net}"] = count
|
|
1377
1369
|
|
|
1378
1370
|
metric_updates_with_aggregates = aggregate_metrics(
|
|
@@ -1511,16 +1503,17 @@ class GlobalPlacementSkipIO(_GlobalPlacement):
|
|
|
1511
1503
|
|
|
1512
1504
|
config_vars = _GlobalPlacement.config_vars + [
|
|
1513
1505
|
Variable(
|
|
1514
|
-
"
|
|
1506
|
+
"IO_PIN_PLACEMENT_MODE",
|
|
1515
1507
|
Literal["matching", "random_equidistant", "annealing"],
|
|
1516
1508
|
"Decides the mode of the random IO placement option.",
|
|
1517
1509
|
default="matching",
|
|
1518
|
-
deprecated_names=[("FP_IO_MODE", _migrate_ppl_mode)],
|
|
1510
|
+
deprecated_names=[("FP_IO_MODE", _migrate_ppl_mode), "FP_PPL_MODE"],
|
|
1519
1511
|
),
|
|
1520
1512
|
Variable(
|
|
1521
|
-
"
|
|
1513
|
+
"IO_PIN_ORDER_CFG",
|
|
1522
1514
|
Optional[Path],
|
|
1523
1515
|
"Path to a custom pin configuration file.",
|
|
1516
|
+
deprecated_names=["FP_PIN_ORDER_CFG"],
|
|
1524
1517
|
),
|
|
1525
1518
|
Variable(
|
|
1526
1519
|
"FP_DEF_TEMPLATE",
|
|
@@ -1536,9 +1529,9 @@ class GlobalPlacementSkipIO(_GlobalPlacement):
|
|
|
1536
1529
|
f"I/O pins were loaded from {self.config['FP_DEF_TEMPLATE']}. Returning state unaltered…"
|
|
1537
1530
|
)
|
|
1538
1531
|
return {}, {}
|
|
1539
|
-
if self.config["
|
|
1532
|
+
if self.config["IO_PIN_ORDER_CFG"] is not None:
|
|
1540
1533
|
info(
|
|
1541
|
-
f"I/O pins to be placed from {self.config['
|
|
1534
|
+
f"I/O pins to be placed from {self.config['IO_PIN_ORDER_CFG']}. Returning state unaltered…"
|
|
1542
1535
|
)
|
|
1543
1536
|
return {}, {}
|
|
1544
1537
|
env["__PL_SKIP_IO"] = "1"
|