librelane 2.4.0.dev0__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 +470 -0
- librelane/__version__.py +43 -0
- librelane/common/__init__.py +61 -0
- librelane/common/cli.py +75 -0
- librelane/common/drc.py +245 -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 +402 -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 +117 -0
- librelane/config/__init__.py +32 -0
- librelane/config/__main__.py +158 -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 +722 -0
- librelane/container.py +264 -0
- librelane/env_info.py +306 -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 +330 -0
- librelane/flows/cli.py +463 -0
- librelane/flows/flow.py +985 -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/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 +81 -0
- librelane/scripts/magic/drc.tcl +79 -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 +47 -0
- librelane/scripts/magic/gds/mag_with_pointers.tcl +32 -0
- librelane/scripts/magic/get_bbox.tcl +11 -0
- librelane/scripts/magic/lef/extras_maglef.tcl +63 -0
- librelane/scripts/magic/lef/maglef.tcl +27 -0
- librelane/scripts/magic/lef.tcl +57 -0
- librelane/scripts/magic/open.tcl +28 -0
- librelane/scripts/magic/wrapper.tcl +19 -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 +574 -0
- librelane/scripts/odbpy/diodes.py +373 -0
- librelane/scripts/odbpy/disconnected_pins.py +305 -0
- librelane/scripts/odbpy/exception_codes.py +17 -0
- librelane/scripts/odbpy/filter_unannotated.py +100 -0
- librelane/scripts/odbpy/io_place.py +482 -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 +395 -0
- librelane/scripts/odbpy/random_place.py +57 -0
- librelane/scripts/odbpy/reader.py +246 -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 +476 -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 +15 -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 +180 -0
- librelane/state/state.py +351 -0
- librelane/steps/__init__.py +61 -0
- librelane/steps/__main__.py +511 -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 +566 -0
- librelane/steps/misc.py +160 -0
- librelane/steps/netgen.py +253 -0
- librelane/steps/odb.py +955 -0
- librelane/steps/openroad.py +2433 -0
- librelane/steps/openroad_alerts.py +102 -0
- librelane/steps/pyosys.py +629 -0
- librelane/steps/step.py +1547 -0
- librelane/steps/tclstep.py +288 -0
- librelane/steps/verilator.py +222 -0
- librelane/steps/yosys.py +371 -0
- librelane-2.4.0.dev0.dist-info/METADATA +151 -0
- librelane-2.4.0.dev0.dist-info/RECORD +166 -0
- librelane-2.4.0.dev0.dist-info/WHEEL +4 -0
- librelane-2.4.0.dev0.dist-info/entry_points.txt +8 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# Copyright 2023 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
|
+
from .metric import Metric, sum_aggregator, min_aggregator, max_aggregator
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Area and Counts
|
|
18
|
+
Metric(
|
|
19
|
+
"design__core__area",
|
|
20
|
+
higher_is_better=False,
|
|
21
|
+
)
|
|
22
|
+
Metric(
|
|
23
|
+
"design__die__area",
|
|
24
|
+
higher_is_better=False,
|
|
25
|
+
)
|
|
26
|
+
Metric(
|
|
27
|
+
"design__instance__area",
|
|
28
|
+
higher_is_better=False,
|
|
29
|
+
)
|
|
30
|
+
Metric(
|
|
31
|
+
"design__instance__count",
|
|
32
|
+
higher_is_better=False,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Power
|
|
36
|
+
Metric(
|
|
37
|
+
"ir__drop__avg",
|
|
38
|
+
higher_is_better=False,
|
|
39
|
+
)
|
|
40
|
+
Metric(
|
|
41
|
+
"ir__drop__worst",
|
|
42
|
+
aggregator=max_aggregator,
|
|
43
|
+
higher_is_better=False,
|
|
44
|
+
)
|
|
45
|
+
Metric(
|
|
46
|
+
"ir__voltage__worst",
|
|
47
|
+
aggregator=min_aggregator,
|
|
48
|
+
higher_is_better=True,
|
|
49
|
+
)
|
|
50
|
+
Metric(
|
|
51
|
+
"design_powergrid__drop__average",
|
|
52
|
+
higher_is_better=False,
|
|
53
|
+
)
|
|
54
|
+
Metric(
|
|
55
|
+
"design_powergrid__drop__worst",
|
|
56
|
+
aggregator=max_aggregator,
|
|
57
|
+
higher_is_better=False,
|
|
58
|
+
)
|
|
59
|
+
Metric(
|
|
60
|
+
"design_powergrid__voltage__worst",
|
|
61
|
+
aggregator=min_aggregator,
|
|
62
|
+
higher_is_better=True,
|
|
63
|
+
)
|
|
64
|
+
Metric(
|
|
65
|
+
"power__internal__total",
|
|
66
|
+
aggregator=sum_aggregator,
|
|
67
|
+
higher_is_better=False,
|
|
68
|
+
)
|
|
69
|
+
Metric(
|
|
70
|
+
"power__leakage__total",
|
|
71
|
+
aggregator=sum_aggregator,
|
|
72
|
+
higher_is_better=False,
|
|
73
|
+
)
|
|
74
|
+
Metric(
|
|
75
|
+
"power__switching__total",
|
|
76
|
+
aggregator=sum_aggregator,
|
|
77
|
+
higher_is_better=False,
|
|
78
|
+
)
|
|
79
|
+
Metric(
|
|
80
|
+
"power__total",
|
|
81
|
+
aggregator=sum_aggregator,
|
|
82
|
+
higher_is_better=False,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Timing
|
|
86
|
+
Metric(
|
|
87
|
+
"timing__hold_vio__count",
|
|
88
|
+
aggregator=sum_aggregator,
|
|
89
|
+
higher_is_better=False,
|
|
90
|
+
critical=True,
|
|
91
|
+
)
|
|
92
|
+
Metric(
|
|
93
|
+
"timing__hold_r2r_vio__count",
|
|
94
|
+
aggregator=sum_aggregator,
|
|
95
|
+
higher_is_better=False,
|
|
96
|
+
critical=True,
|
|
97
|
+
)
|
|
98
|
+
Metric(
|
|
99
|
+
"timing__setup_vio__count",
|
|
100
|
+
aggregator=sum_aggregator,
|
|
101
|
+
higher_is_better=False,
|
|
102
|
+
critical=True,
|
|
103
|
+
)
|
|
104
|
+
Metric(
|
|
105
|
+
"timing__setup_r2r_vio__count",
|
|
106
|
+
aggregator=sum_aggregator,
|
|
107
|
+
higher_is_better=False,
|
|
108
|
+
critical=True,
|
|
109
|
+
)
|
|
110
|
+
Metric(
|
|
111
|
+
"timing__hold__ws",
|
|
112
|
+
aggregator=min_aggregator,
|
|
113
|
+
higher_is_better=True,
|
|
114
|
+
)
|
|
115
|
+
Metric(
|
|
116
|
+
"timing__hold_r2r__ws",
|
|
117
|
+
aggregator=min_aggregator,
|
|
118
|
+
higher_is_better=True,
|
|
119
|
+
)
|
|
120
|
+
Metric(
|
|
121
|
+
"timing__setup__ws",
|
|
122
|
+
aggregator=min_aggregator,
|
|
123
|
+
higher_is_better=True,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
Metric(
|
|
127
|
+
"timing__setup_r2r__ws",
|
|
128
|
+
aggregator=min_aggregator,
|
|
129
|
+
higher_is_better=True,
|
|
130
|
+
)
|
|
131
|
+
Metric(
|
|
132
|
+
"timing__hold__wns",
|
|
133
|
+
aggregator=min_aggregator,
|
|
134
|
+
higher_is_better=True,
|
|
135
|
+
critical=True,
|
|
136
|
+
)
|
|
137
|
+
Metric(
|
|
138
|
+
"timing__setup__wns",
|
|
139
|
+
aggregator=min_aggregator,
|
|
140
|
+
higher_is_better=True,
|
|
141
|
+
critical=True,
|
|
142
|
+
)
|
|
143
|
+
Metric(
|
|
144
|
+
"timing__hold__tns",
|
|
145
|
+
aggregator=min_aggregator,
|
|
146
|
+
higher_is_better=True,
|
|
147
|
+
critical=True,
|
|
148
|
+
)
|
|
149
|
+
Metric(
|
|
150
|
+
"timing__unannotated_net__count",
|
|
151
|
+
aggregator=max_aggregator,
|
|
152
|
+
higher_is_better=False,
|
|
153
|
+
)
|
|
154
|
+
Metric(
|
|
155
|
+
"timing__unannotated_net_filtered__count",
|
|
156
|
+
aggregator=max_aggregator,
|
|
157
|
+
higher_is_better=False,
|
|
158
|
+
)
|
|
159
|
+
Metric(
|
|
160
|
+
"timing__setup__tns",
|
|
161
|
+
aggregator=min_aggregator,
|
|
162
|
+
higher_is_better=True,
|
|
163
|
+
critical=True,
|
|
164
|
+
)
|
|
165
|
+
Metric(
|
|
166
|
+
"clock__skew__worst_hold",
|
|
167
|
+
aggregator=max_aggregator,
|
|
168
|
+
higher_is_better=False,
|
|
169
|
+
)
|
|
170
|
+
Metric(
|
|
171
|
+
"clock__skew__worst_setup",
|
|
172
|
+
aggregator=min_aggregator,
|
|
173
|
+
higher_is_better=True,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Constraint Violation
|
|
177
|
+
Metric(
|
|
178
|
+
"design__max_slew_violation__count",
|
|
179
|
+
aggregator=max_aggregator,
|
|
180
|
+
higher_is_better=False,
|
|
181
|
+
)
|
|
182
|
+
Metric(
|
|
183
|
+
"design__max_fanout_violation__count",
|
|
184
|
+
aggregator=max_aggregator,
|
|
185
|
+
higher_is_better=False,
|
|
186
|
+
)
|
|
187
|
+
Metric(
|
|
188
|
+
"design__max_cap_violation__count",
|
|
189
|
+
aggregator=max_aggregator,
|
|
190
|
+
higher_is_better=False,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Placement and Routing
|
|
194
|
+
Metric(
|
|
195
|
+
"route__wirelength",
|
|
196
|
+
aggregator=sum_aggregator,
|
|
197
|
+
higher_is_better=False,
|
|
198
|
+
dont_aggregate=["iter"],
|
|
199
|
+
)
|
|
200
|
+
Metric(
|
|
201
|
+
"route__wirelength__estimated",
|
|
202
|
+
aggregator=sum_aggregator,
|
|
203
|
+
higher_is_better=False,
|
|
204
|
+
dont_aggregate=["iter"],
|
|
205
|
+
)
|
|
206
|
+
Metric(
|
|
207
|
+
"route__wirelength__max",
|
|
208
|
+
aggregator=max_aggregator,
|
|
209
|
+
higher_is_better=False,
|
|
210
|
+
dont_aggregate=["iter"],
|
|
211
|
+
)
|
|
212
|
+
Metric(
|
|
213
|
+
"route__antenna_violation__count",
|
|
214
|
+
aggregator=sum_aggregator,
|
|
215
|
+
higher_is_better=False,
|
|
216
|
+
dont_aggregate=["iter"],
|
|
217
|
+
)
|
|
218
|
+
Metric(
|
|
219
|
+
"design__instance__displacement__max",
|
|
220
|
+
aggregator=max_aggregator,
|
|
221
|
+
higher_is_better=False,
|
|
222
|
+
)
|
|
223
|
+
Metric(
|
|
224
|
+
"design__instance__displacement__total",
|
|
225
|
+
aggregator=sum_aggregator,
|
|
226
|
+
higher_is_better=False,
|
|
227
|
+
)
|
|
228
|
+
Metric(
|
|
229
|
+
"design__instance__utilization",
|
|
230
|
+
higher_is_better=True,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Potential Issues
|
|
234
|
+
Metric(
|
|
235
|
+
"design__lint_warning__count",
|
|
236
|
+
aggregator=sum_aggregator,
|
|
237
|
+
higher_is_better=False,
|
|
238
|
+
)
|
|
239
|
+
Metric(
|
|
240
|
+
"design__lint_error__count",
|
|
241
|
+
aggregator=sum_aggregator,
|
|
242
|
+
higher_is_better=False,
|
|
243
|
+
critical=True,
|
|
244
|
+
)
|
|
245
|
+
Metric(
|
|
246
|
+
"design__lint_timing_construct__count",
|
|
247
|
+
aggregator=sum_aggregator,
|
|
248
|
+
higher_is_better=False,
|
|
249
|
+
)
|
|
250
|
+
Metric(
|
|
251
|
+
"antenna__violating__nets",
|
|
252
|
+
aggregator=sum_aggregator,
|
|
253
|
+
higher_is_better=False,
|
|
254
|
+
)
|
|
255
|
+
Metric(
|
|
256
|
+
"antenna__violating__pins",
|
|
257
|
+
aggregator=sum_aggregator,
|
|
258
|
+
higher_is_better=False,
|
|
259
|
+
)
|
|
260
|
+
Metric(
|
|
261
|
+
"design__instance_unmapped__count",
|
|
262
|
+
aggregator=sum_aggregator,
|
|
263
|
+
higher_is_better=False,
|
|
264
|
+
critical=True,
|
|
265
|
+
)
|
|
266
|
+
Metric(
|
|
267
|
+
"design__disconnected_pin__count",
|
|
268
|
+
aggregator=sum_aggregator,
|
|
269
|
+
higher_is_better=False,
|
|
270
|
+
critical=True,
|
|
271
|
+
)
|
|
272
|
+
Metric(
|
|
273
|
+
"design__inferred_latch__count",
|
|
274
|
+
aggregator=sum_aggregator,
|
|
275
|
+
higher_is_better=False,
|
|
276
|
+
)
|
|
277
|
+
Metric(
|
|
278
|
+
"design__violations",
|
|
279
|
+
aggregator=sum_aggregator,
|
|
280
|
+
higher_is_better=False,
|
|
281
|
+
)
|
|
282
|
+
Metric(
|
|
283
|
+
"design__xor_difference__count",
|
|
284
|
+
aggregator=sum_aggregator,
|
|
285
|
+
higher_is_better=False,
|
|
286
|
+
critical=True,
|
|
287
|
+
)
|
|
288
|
+
Metric(
|
|
289
|
+
"route__drc_errors",
|
|
290
|
+
aggregator=sum_aggregator,
|
|
291
|
+
higher_is_better=False,
|
|
292
|
+
dont_aggregate=["iter"],
|
|
293
|
+
critical=True,
|
|
294
|
+
)
|
|
295
|
+
Metric(
|
|
296
|
+
"magic__drc_error__count",
|
|
297
|
+
aggregator=sum_aggregator,
|
|
298
|
+
higher_is_better=False,
|
|
299
|
+
critical=True,
|
|
300
|
+
)
|
|
301
|
+
Metric(
|
|
302
|
+
"magic__illegal_overlap__count",
|
|
303
|
+
aggregator=sum_aggregator,
|
|
304
|
+
higher_is_better=False,
|
|
305
|
+
critical=True,
|
|
306
|
+
)
|
|
307
|
+
Metric(
|
|
308
|
+
"synthesis__check_error__count",
|
|
309
|
+
aggregator=sum_aggregator,
|
|
310
|
+
higher_is_better=False,
|
|
311
|
+
critical=True,
|
|
312
|
+
)
|
|
313
|
+
Metric(
|
|
314
|
+
"design__lvs_error__count",
|
|
315
|
+
aggregator=sum_aggregator,
|
|
316
|
+
higher_is_better=False,
|
|
317
|
+
critical=True,
|
|
318
|
+
)
|
|
319
|
+
Metric(
|
|
320
|
+
"design__lvs_device_difference__count",
|
|
321
|
+
aggregator=sum_aggregator,
|
|
322
|
+
higher_is_better=False,
|
|
323
|
+
critical=True,
|
|
324
|
+
)
|
|
325
|
+
Metric(
|
|
326
|
+
"design__lvs_net_difference__count",
|
|
327
|
+
aggregator=sum_aggregator,
|
|
328
|
+
higher_is_better=False,
|
|
329
|
+
critical=True,
|
|
330
|
+
)
|
|
331
|
+
Metric(
|
|
332
|
+
"design__lvs_property_fail__count",
|
|
333
|
+
aggregator=sum_aggregator,
|
|
334
|
+
higher_is_better=False,
|
|
335
|
+
critical=True,
|
|
336
|
+
)
|
|
337
|
+
Metric(
|
|
338
|
+
"design__lvs_unmatched_device__count",
|
|
339
|
+
aggregator=sum_aggregator,
|
|
340
|
+
higher_is_better=False,
|
|
341
|
+
critical=True,
|
|
342
|
+
)
|
|
343
|
+
Metric(
|
|
344
|
+
"design__lvs_unmatched_net__count",
|
|
345
|
+
aggregator=sum_aggregator,
|
|
346
|
+
higher_is_better=False,
|
|
347
|
+
critical=True,
|
|
348
|
+
)
|
|
349
|
+
Metric(
|
|
350
|
+
"design__lvs_unmatched_pin__count",
|
|
351
|
+
aggregator=sum_aggregator,
|
|
352
|
+
higher_is_better=False,
|
|
353
|
+
critical=True,
|
|
354
|
+
)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Copyright 2023 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
|
+
from math import inf
|
|
15
|
+
from decimal import Decimal
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from typing import Any, Callable, Iterable, Mapping, Optional, Tuple, ClassVar, Dict
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from ..types import Number, is_number, is_real_number
|
|
21
|
+
|
|
22
|
+
MetricAggregator = Tuple[Number, Callable[[Iterable[Number]], Number]]
|
|
23
|
+
|
|
24
|
+
sum_aggregator: MetricAggregator = (0, lambda x: sum(x))
|
|
25
|
+
min_aggregator: MetricAggregator = (inf, min)
|
|
26
|
+
max_aggregator: MetricAggregator = (-inf, max)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class MetricComparisonResult:
|
|
31
|
+
"""
|
|
32
|
+
:param metric_name: The name of the metric that has been compared
|
|
33
|
+
:param gold: The "gold" value being compared against
|
|
34
|
+
:param new: The new value being evaluated
|
|
35
|
+
:param delta: ``None`` if and only if ``before`` - ``after`` is an invalid number.
|
|
36
|
+
Evaluates to ``after - before``\\.
|
|
37
|
+
:param delta_pct: ``None`` if ``delta`` is None or before is zero.
|
|
38
|
+
Otherwise, evaluates to ``delta / before * 100``\\.
|
|
39
|
+
:param better: Whether the change in the value is considered a good thing or
|
|
40
|
+
not. ``None`` if ``delta`` is None or has no value set for
|
|
41
|
+
``Metric.higher_is_better``\\.
|
|
42
|
+
:param critical: Whether this change of value very likely results in a dead
|
|
43
|
+
chip, i.e., an increase in DRC values, or an inexplicable change in
|
|
44
|
+
the number of I/O pins.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
metric_name: str
|
|
49
|
+
gold: Any
|
|
50
|
+
new: Any
|
|
51
|
+
delta: Optional[Number]
|
|
52
|
+
delta_pct: Optional[Number]
|
|
53
|
+
better: Optional[bool]
|
|
54
|
+
critical: bool
|
|
55
|
+
significant_figures: Optional[int]
|
|
56
|
+
|
|
57
|
+
def is_changed(self) -> bool:
|
|
58
|
+
return (self.delta is not None and self.delta != 0) or self.gold != self.new
|
|
59
|
+
|
|
60
|
+
def format_values(self) -> Tuple[str, str, str]:
|
|
61
|
+
before_str = str(self.gold)
|
|
62
|
+
if isinstance(self.gold, float) or isinstance(self.gold, Decimal):
|
|
63
|
+
before_str = str(f"{self.gold:.{self.significant_figures}f}")
|
|
64
|
+
|
|
65
|
+
after_str = str(self.new)
|
|
66
|
+
if isinstance(self.new, float) or isinstance(self.new, Decimal):
|
|
67
|
+
after_str = str(f"{self.new:.{self.significant_figures}f}")
|
|
68
|
+
|
|
69
|
+
delta_str = "N/A"
|
|
70
|
+
if self.delta is not None:
|
|
71
|
+
delta_str = str(round(self.delta, 6))
|
|
72
|
+
if isinstance(self.delta, float) or isinstance(self.delta, Decimal):
|
|
73
|
+
delta_str = str(f"{self.delta:.{self.significant_figures}f}")
|
|
74
|
+
if self.delta_pct is not None:
|
|
75
|
+
delta_pct_str = str(f"{self.delta_pct:.{self.significant_figures}f}")
|
|
76
|
+
if self.delta_pct > 0:
|
|
77
|
+
delta_pct_str = f"+{delta_pct_str}"
|
|
78
|
+
delta_str = f"{delta_str} ({delta_pct_str}%)"
|
|
79
|
+
|
|
80
|
+
return before_str, after_str, delta_str
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class Metric(object):
|
|
85
|
+
"""
|
|
86
|
+
An object storing data about a metric as defined in METRICS2.1.
|
|
87
|
+
|
|
88
|
+
:param name: The string name of the metric.
|
|
89
|
+
:param aggregator: A tuple of:
|
|
90
|
+
- A starting value for an accumulator
|
|
91
|
+
- A reduction function
|
|
92
|
+
|
|
93
|
+
The aim is the ability to aggregate values from various sub-metrics,
|
|
94
|
+
i.e., for the metric ``timing__hold_vio__count``, the sub-metrics:
|
|
95
|
+
|
|
96
|
+
- ``timing__hold_vio__count__corner:A``
|
|
97
|
+
- ``timing__hold_vio__count__corner:B``
|
|
98
|
+
|
|
99
|
+
Would be summed up to generate the value for ``timing__hold_vio__count``.
|
|
100
|
+
:param higher_is_better: At a high level, whether a higher numeric value for
|
|
101
|
+
this metric is considered "good" (such as: better utilization) or "bad"
|
|
102
|
+
(such as: more antenna violations.)
|
|
103
|
+
:param critical: A critical metric is always watched for any change.
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
name: str
|
|
108
|
+
aggregator: Optional[MetricAggregator] = None
|
|
109
|
+
higher_is_better: Optional[bool] = None
|
|
110
|
+
dont_aggregate: Optional[Iterable[str]] = None
|
|
111
|
+
critical: bool = False
|
|
112
|
+
|
|
113
|
+
by_name: ClassVar[Dict[str, "Metric"]] = {}
|
|
114
|
+
|
|
115
|
+
def __post_init__(self):
|
|
116
|
+
Metric.by_name[self.name] = self
|
|
117
|
+
|
|
118
|
+
def modified_name(self, modifiers: Mapping[str, str]) -> str:
|
|
119
|
+
"""
|
|
120
|
+
:param modifiers: Modifiers of a metric (i.e. the elements postfixed to the metric in the format {key}:{value})
|
|
121
|
+
:returns: The name with the modifiers added
|
|
122
|
+
"""
|
|
123
|
+
return "__".join([self.name] + [f"{k}:{v}" for k, v in modifiers.items()])
|
|
124
|
+
|
|
125
|
+
def compare(
|
|
126
|
+
self,
|
|
127
|
+
gold: Any,
|
|
128
|
+
new: Any,
|
|
129
|
+
significant_figures: int,
|
|
130
|
+
modifiers: Optional[Mapping[str, str]] = None,
|
|
131
|
+
) -> MetricComparisonResult:
|
|
132
|
+
"""
|
|
133
|
+
:param gold: The "gold-standard" value for this metric to compare against
|
|
134
|
+
:param new: The new value for this metric being evaluated
|
|
135
|
+
:param modifier: The modifiers that were parsed from the metric name
|
|
136
|
+
(if applicable)- used to set the ``metric_name`` property of
|
|
137
|
+
:class:`MetricComparisonResult`.
|
|
138
|
+
:returns: The result of comparing two values for this metric.
|
|
139
|
+
"""
|
|
140
|
+
is_better = None
|
|
141
|
+
is_critical = self.critical and (gold != new)
|
|
142
|
+
delta = None
|
|
143
|
+
delta_pct = None
|
|
144
|
+
|
|
145
|
+
if modifiers is None:
|
|
146
|
+
modifiers = {}
|
|
147
|
+
|
|
148
|
+
if is_real_number(gold) and is_real_number(new):
|
|
149
|
+
if isinstance(gold, float) or isinstance(new, float):
|
|
150
|
+
gold = Decimal(gold)
|
|
151
|
+
new = Decimal(new)
|
|
152
|
+
delta = new - gold
|
|
153
|
+
|
|
154
|
+
if gold == 0:
|
|
155
|
+
if new == 0:
|
|
156
|
+
delta_pct = Decimal(0)
|
|
157
|
+
else:
|
|
158
|
+
delta_pct = Decimal((delta / gold) * 100)
|
|
159
|
+
if delta_pct == 0:
|
|
160
|
+
delta_pct = Decimal(0) # Fix negative zero
|
|
161
|
+
|
|
162
|
+
if self.higher_is_better is not None:
|
|
163
|
+
if self.higher_is_better:
|
|
164
|
+
is_better = delta >= 0
|
|
165
|
+
else:
|
|
166
|
+
is_better = delta <= 0
|
|
167
|
+
elif self.higher_is_better is not None:
|
|
168
|
+
if not is_number(gold):
|
|
169
|
+
raise TypeError(
|
|
170
|
+
f"'{gold}' is not a number for metric {self.name} with non-None 'higher_is_better' field"
|
|
171
|
+
)
|
|
172
|
+
if not is_number(new):
|
|
173
|
+
raise TypeError(
|
|
174
|
+
f"'{new}' is not a number for metric {self.name} with non-None 'higher_is_better' field"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return MetricComparisonResult(
|
|
178
|
+
self.modified_name(modifiers),
|
|
179
|
+
gold,
|
|
180
|
+
new,
|
|
181
|
+
delta,
|
|
182
|
+
delta_pct,
|
|
183
|
+
is_better,
|
|
184
|
+
is_critical,
|
|
185
|
+
significant_figures,
|
|
186
|
+
)
|