siliconcompiler 0.35.3__py3-none-any.whl → 0.36.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.
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/sc_issue.py +18 -2
- siliconcompiler/checklist.py +2 -1
- siliconcompiler/constraints/__init__.py +4 -1
- siliconcompiler/constraints/asic_component.py +49 -11
- siliconcompiler/constraints/asic_floorplan.py +23 -21
- siliconcompiler/constraints/asic_pins.py +55 -17
- siliconcompiler/constraints/asic_timing.py +280 -57
- siliconcompiler/constraints/fpga_timing.py +212 -18
- siliconcompiler/constraints/timing_mode.py +82 -0
- siliconcompiler/data/templates/replay/replay.sh.j2 +27 -14
- siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
- siliconcompiler/flowgraph.py +95 -42
- siliconcompiler/flows/generate_openroad_rcx.py +2 -2
- siliconcompiler/flows/highresscreenshotflow.py +37 -0
- siliconcompiler/library.py +2 -1
- siliconcompiler/package/__init__.py +56 -51
- siliconcompiler/project.py +13 -2
- siliconcompiler/scheduler/docker.py +24 -25
- siliconcompiler/scheduler/scheduler.py +143 -100
- siliconcompiler/scheduler/schedulernode.py +138 -22
- siliconcompiler/scheduler/slurm.py +120 -35
- siliconcompiler/scheduler/taskscheduler.py +19 -23
- siliconcompiler/schema/_metadata.py +1 -1
- siliconcompiler/schema/editableschema.py +29 -0
- siliconcompiler/schema/namedschema.py +2 -4
- siliconcompiler/schema/parametervalue.py +14 -2
- siliconcompiler/schema_support/cmdlineschema.py +0 -3
- siliconcompiler/schema_support/dependencyschema.py +0 -6
- siliconcompiler/schema_support/option.py +82 -1
- siliconcompiler/schema_support/pathschema.py +7 -13
- siliconcompiler/schema_support/record.py +4 -3
- siliconcompiler/tool.py +105 -52
- siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
- siliconcompiler/tools/keplerformal/__init__.py +7 -0
- siliconcompiler/tools/keplerformal/lec.py +112 -0
- siliconcompiler/tools/klayout/__init__.py +3 -0
- siliconcompiler/tools/klayout/screenshot.py +66 -1
- siliconcompiler/tools/klayout/scripts/klayout_convert_drc_db.py +1 -0
- siliconcompiler/tools/klayout/scripts/klayout_export.py +11 -40
- siliconcompiler/tools/klayout/scripts/klayout_operations.py +1 -0
- siliconcompiler/tools/klayout/scripts/klayout_show.py +5 -4
- siliconcompiler/tools/klayout/scripts/klayout_utils.py +16 -5
- siliconcompiler/tools/montage/tile.py +26 -12
- siliconcompiler/tools/openroad/__init__.py +27 -1
- siliconcompiler/tools/openroad/_apr.py +107 -14
- siliconcompiler/tools/openroad/clock_tree_synthesis.py +1 -0
- siliconcompiler/tools/openroad/global_placement.py +1 -0
- siliconcompiler/tools/openroad/init_floorplan.py +119 -7
- siliconcompiler/tools/openroad/power_grid_analysis.py +174 -0
- siliconcompiler/tools/openroad/repair_design.py +1 -0
- siliconcompiler/tools/openroad/repair_timing.py +1 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +91 -18
- siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +148 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +8 -10
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +15 -6
- siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +7 -4
- siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
- siliconcompiler/tools/openroad/scripts/rcx/sc_rcx_bench.tcl +2 -4
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
- siliconcompiler/tools/openroad/write_data.py +2 -2
- siliconcompiler/tools/opensta/__init__.py +1 -1
- siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +13 -10
- siliconcompiler/tools/opensta/timing.py +6 -2
- siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_place.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_route.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +10 -0
- siliconcompiler/tools/vpr/__init__.py +28 -0
- siliconcompiler/tools/yosys/scripts/sc_screenshot.tcl +1 -1
- siliconcompiler/tools/yosys/scripts/sc_synth_asic.tcl +40 -4
- siliconcompiler/tools/yosys/scripts/sc_synth_fpga.tcl +15 -5
- siliconcompiler/tools/yosys/syn_asic.py +42 -0
- siliconcompiler/tools/yosys/syn_fpga.py +8 -0
- siliconcompiler/toolscripts/_tools.json +12 -7
- siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
- siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
- siliconcompiler/utils/__init__.py +243 -51
- siliconcompiler/utils/curation.py +89 -56
- siliconcompiler/utils/issue.py +6 -1
- siliconcompiler/utils/multiprocessing.py +46 -2
- siliconcompiler/utils/paths.py +21 -0
- siliconcompiler/utils/settings.py +162 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/METADATA +5 -4
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/RECORD +96 -87
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
from typing import Union, Set, List, Tuple
|
|
1
|
+
from typing import Union, Set, List, Tuple, Optional, Dict
|
|
2
2
|
|
|
3
3
|
from siliconcompiler.schema import BaseSchema, NamedSchema, EditableSchema, Parameter, \
|
|
4
4
|
PerNode, Scope
|
|
5
5
|
from siliconcompiler import Design
|
|
6
|
+
from siliconcompiler.constraints.timing_mode import TimingModeSchema
|
|
7
|
+
from siliconcompiler.schema.baseschema import LazyLoad
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class ASICTimingScenarioSchema(NamedSchema):
|
|
@@ -14,7 +16,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
14
16
|
operating mode, SDC filesets, and timing checks to be performed.
|
|
15
17
|
"""
|
|
16
18
|
|
|
17
|
-
def __init__(self, name: str = None):
|
|
19
|
+
def __init__(self, name: Optional[str] = None):
|
|
18
20
|
super().__init__()
|
|
19
21
|
self.set_name(name)
|
|
20
22
|
|
|
@@ -93,20 +95,6 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
93
95
|
help="""Operating mode for the scenario. Operating mode strings
|
|
94
96
|
can be values such as test, functional, standby."""))
|
|
95
97
|
|
|
96
|
-
schema.insert(
|
|
97
|
-
'sdcfileset',
|
|
98
|
-
Parameter(
|
|
99
|
-
'[(str,str)]',
|
|
100
|
-
pernode=PerNode.OPTIONAL,
|
|
101
|
-
scope=Scope.GLOBAL,
|
|
102
|
-
shorthelp="Constraint: SDC files",
|
|
103
|
-
switch="-constraint_timing_file 'scenario <file>'",
|
|
104
|
-
example=["api: asic.set('constraint', 'timing', 'worst', 'file', 'hello.sdc')"],
|
|
105
|
-
help="""List of timing constraint sets files to use for the scenario. The
|
|
106
|
-
values are combined with any constraints specified by the design
|
|
107
|
-
'constraint' parameter. If no constraints are found, a default
|
|
108
|
-
constraint file is used based on the clock definitions."""))
|
|
109
|
-
|
|
110
98
|
schema.insert(
|
|
111
99
|
'check',
|
|
112
100
|
Parameter(
|
|
@@ -126,7 +114,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
126
114
|
def set_pin_voltage(self,
|
|
127
115
|
pin: str,
|
|
128
116
|
voltage: float,
|
|
129
|
-
step: str = None, index: Union[str, int] = None):
|
|
117
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
130
118
|
"""
|
|
131
119
|
Sets the voltage for a specified pin.
|
|
132
120
|
|
|
@@ -140,7 +128,8 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
140
128
|
|
|
141
129
|
def get_pin_voltage(self,
|
|
142
130
|
pin: str,
|
|
143
|
-
step: str = None, index: Union[str, int] = None)
|
|
131
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
132
|
+
-> float:
|
|
144
133
|
"""
|
|
145
134
|
Gets the voltage of a specified pin.
|
|
146
135
|
|
|
@@ -162,7 +151,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
162
151
|
def add_libcorner(self,
|
|
163
152
|
libcorner: Union[List[str], str],
|
|
164
153
|
clobber: bool = False,
|
|
165
|
-
step: str = None, index: Union[str, int] = None):
|
|
154
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
166
155
|
"""
|
|
167
156
|
Adds a library corner to the design.
|
|
168
157
|
|
|
@@ -179,8 +168,8 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
179
168
|
else:
|
|
180
169
|
return self.add("libcorner", libcorner, step=step, index=index)
|
|
181
170
|
|
|
182
|
-
def get_libcorner(self,
|
|
183
|
-
|
|
171
|
+
def get_libcorner(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
172
|
+
-> Set[str]:
|
|
184
173
|
"""
|
|
185
174
|
Gets the set of library corners.
|
|
186
175
|
|
|
@@ -195,7 +184,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
195
184
|
|
|
196
185
|
def set_pexcorner(self,
|
|
197
186
|
pexcorner: str,
|
|
198
|
-
step: str = None, index: Union[str, int] = None):
|
|
187
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
199
188
|
"""
|
|
200
189
|
Sets the parasitic extraction (PEX) corner for the design.
|
|
201
190
|
|
|
@@ -207,7 +196,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
207
196
|
return self.set("pexcorner", pexcorner, step=step, index=index)
|
|
208
197
|
|
|
209
198
|
def get_pexcorner(self,
|
|
210
|
-
step: str = None, index: Union[str, int] = None) -> str:
|
|
199
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None) -> str:
|
|
211
200
|
"""
|
|
212
201
|
Gets the parasitic extraction (PEX) corner currently set for the design.
|
|
213
202
|
|
|
@@ -222,7 +211,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
222
211
|
|
|
223
212
|
def set_mode(self,
|
|
224
213
|
mode: str,
|
|
225
|
-
step: str = None, index: Union[str, int] = None):
|
|
214
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
226
215
|
"""
|
|
227
216
|
Sets the operational mode for the design.
|
|
228
217
|
|
|
@@ -234,7 +223,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
234
223
|
return self.set("mode", mode, step=step, index=index)
|
|
235
224
|
|
|
236
225
|
def get_mode(self,
|
|
237
|
-
step: str = None, index: Union[str, int] = None) -> str:
|
|
226
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None) -> str:
|
|
238
227
|
"""
|
|
239
228
|
Gets the operational mode currently set for the design.
|
|
240
229
|
|
|
@@ -249,7 +238,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
249
238
|
|
|
250
239
|
def set_opcond(self,
|
|
251
240
|
opcond: str,
|
|
252
|
-
step: str = None, index: Union[str, int] = None):
|
|
241
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
253
242
|
"""
|
|
254
243
|
Sets the operating condition for the design.
|
|
255
244
|
|
|
@@ -261,7 +250,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
261
250
|
return self.set("opcond", opcond, step=step, index=index)
|
|
262
251
|
|
|
263
252
|
def get_opcond(self,
|
|
264
|
-
step: str = None, index: Union[str, int] = None) -> str:
|
|
253
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None) -> str:
|
|
265
254
|
"""
|
|
266
255
|
Gets the operating condition currently set for the design.
|
|
267
256
|
|
|
@@ -276,7 +265,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
276
265
|
|
|
277
266
|
def set_temperature(self,
|
|
278
267
|
temperature: float,
|
|
279
|
-
step: str = None, index: Union[str, int] = None):
|
|
268
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
280
269
|
"""
|
|
281
270
|
Sets the temperature for the design.
|
|
282
271
|
|
|
@@ -287,8 +276,8 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
287
276
|
"""
|
|
288
277
|
return self.set("temperature", temperature, step=step, index=index)
|
|
289
278
|
|
|
290
|
-
def get_temperature(self,
|
|
291
|
-
|
|
279
|
+
def get_temperature(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
280
|
+
-> float:
|
|
292
281
|
"""
|
|
293
282
|
Gets the temperature currently set for the design.
|
|
294
283
|
|
|
@@ -305,7 +294,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
305
294
|
design: Union[Design, str],
|
|
306
295
|
fileset: str,
|
|
307
296
|
clobber: bool = False,
|
|
308
|
-
step: str = None, index: Union[str, int] = None):
|
|
297
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
309
298
|
"""
|
|
310
299
|
Adds an SDC fileset for a given design.
|
|
311
300
|
|
|
@@ -323,22 +312,25 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
323
312
|
TypeError: If `design` is not a Design object or a string, or if `fileset` is not
|
|
324
313
|
a string.
|
|
325
314
|
"""
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if not isinstance(design, str):
|
|
330
|
-
raise TypeError("design must be a design object or string")
|
|
315
|
+
import warnings
|
|
316
|
+
warnings.warn("This function is deprecated and will be removed in a future version, "
|
|
317
|
+
"use TimingModeSchema instead", DeprecationWarning, stacklevel=2)
|
|
331
318
|
|
|
332
|
-
|
|
333
|
-
|
|
319
|
+
mode = self.get_mode(step=step, index=index)
|
|
320
|
+
if mode is None:
|
|
321
|
+
raise ValueError("Mode not defined")
|
|
334
322
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
323
|
+
timing_constraints: ASICTimingConstraintSchema = self._parent()._parent()
|
|
324
|
+
try:
|
|
325
|
+
modeobj = timing_constraints.get_mode(mode)
|
|
326
|
+
except LookupError:
|
|
327
|
+
modeobj = timing_constraints.make_mode(mode)
|
|
328
|
+
return modeobj.add_sdcfileset(design=design, fileset=fileset,
|
|
329
|
+
clobber=clobber,
|
|
330
|
+
step=step, index=index)
|
|
339
331
|
|
|
340
|
-
def get_sdcfileset(self,
|
|
341
|
-
|
|
332
|
+
def get_sdcfileset(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
333
|
+
-> List[Tuple[str, str]]:
|
|
342
334
|
"""
|
|
343
335
|
Gets the list of SDC filesets.
|
|
344
336
|
|
|
@@ -349,12 +341,25 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
349
341
|
Returns:
|
|
350
342
|
A list of tuples, where each tuple contains the design name and the SDC fileset name.
|
|
351
343
|
"""
|
|
352
|
-
|
|
344
|
+
import warnings
|
|
345
|
+
warnings.warn("This function is deprecated and will be removed in a future version, "
|
|
346
|
+
"use TimingModeSchema instead", DeprecationWarning, stacklevel=2)
|
|
347
|
+
|
|
348
|
+
mode = self.get_mode(step=step, index=index)
|
|
349
|
+
if mode is None:
|
|
350
|
+
raise ValueError("Mode not defined")
|
|
351
|
+
|
|
352
|
+
timing_constraints: ASICTimingConstraintSchema = self._parent()._parent()
|
|
353
|
+
try:
|
|
354
|
+
modeobj = timing_constraints.get_mode(mode)
|
|
355
|
+
except LookupError:
|
|
356
|
+
modeobj = timing_constraints.make_mode(mode)
|
|
357
|
+
return modeobj.get_sdcfileset(step=step, index=index)
|
|
353
358
|
|
|
354
359
|
def add_check(self,
|
|
355
360
|
check: Union[List[str], str],
|
|
356
361
|
clobber: bool = False,
|
|
357
|
-
step: str = None, index: Union[str, int] = None):
|
|
362
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
358
363
|
"""
|
|
359
364
|
Adds a check to the design process.
|
|
360
365
|
|
|
@@ -371,7 +376,8 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
371
376
|
else:
|
|
372
377
|
return self.add("check", check, step=step, index=index)
|
|
373
378
|
|
|
374
|
-
def get_check(self, step: str = None, index: Union[str, int] = None)
|
|
379
|
+
def get_check(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
380
|
+
-> Set[str]:
|
|
375
381
|
"""
|
|
376
382
|
Gets the set of checks configured for the design process.
|
|
377
383
|
|
|
@@ -384,6 +390,30 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
384
390
|
"""
|
|
385
391
|
return self.get("check", step=step, index=index)
|
|
386
392
|
|
|
393
|
+
def _from_dict(self, manifest: Dict,
|
|
394
|
+
keypath: Union[List[str], Tuple[str, ...]],
|
|
395
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
396
|
+
lazyload: LazyLoad = LazyLoad.ON) \
|
|
397
|
+
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
398
|
+
|
|
399
|
+
sdcfileset = None
|
|
400
|
+
if version and version < (0, 53, 0):
|
|
401
|
+
sdcfileset = manifest.pop("sdcfileset", None)
|
|
402
|
+
lazyload = LazyLoad.OFF
|
|
403
|
+
|
|
404
|
+
ret = super()._from_dict(manifest, keypath, version, lazyload)
|
|
405
|
+
|
|
406
|
+
if sdcfileset:
|
|
407
|
+
param = Parameter.from_dict(sdcfileset, keypath=(*keypath, "sdcfileset"),
|
|
408
|
+
version=version)
|
|
409
|
+
for value, step, index in param.getvalues():
|
|
410
|
+
if self.get_mode(step=step, index=index) is None:
|
|
411
|
+
self.set_mode("_importcreated_", step=step, index=index)
|
|
412
|
+
for design, fileset in value:
|
|
413
|
+
self.add_sdcfileset(design, fileset, step=step, index=index)
|
|
414
|
+
|
|
415
|
+
return ret
|
|
416
|
+
|
|
387
417
|
|
|
388
418
|
class ASICTimingConstraintSchema(BaseSchema):
|
|
389
419
|
"""
|
|
@@ -398,7 +428,8 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
398
428
|
def __init__(self):
|
|
399
429
|
super().__init__()
|
|
400
430
|
|
|
401
|
-
EditableSchema(self).insert("default", ASICTimingScenarioSchema())
|
|
431
|
+
EditableSchema(self).insert("scenario", "default", ASICTimingScenarioSchema())
|
|
432
|
+
EditableSchema(self).insert("mode", "default", TimingModeSchema())
|
|
402
433
|
|
|
403
434
|
def add_scenario(self, scenario: ASICTimingScenarioSchema):
|
|
404
435
|
"""
|
|
@@ -424,9 +455,10 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
424
455
|
if scenario.name is None:
|
|
425
456
|
raise ValueError("scenario must have a name")
|
|
426
457
|
|
|
427
|
-
EditableSchema(self).insert(scenario.name, scenario, clobber=True)
|
|
458
|
+
EditableSchema(self).insert("scenario", scenario.name, scenario, clobber=True)
|
|
428
459
|
|
|
429
|
-
def get_scenario(self, scenario: str = None)
|
|
460
|
+
def get_scenario(self, scenario: Optional[str] = None) \
|
|
461
|
+
-> Union[ASICTimingScenarioSchema, Dict[str, ASICTimingScenarioSchema]]:
|
|
430
462
|
"""
|
|
431
463
|
Retrieves one or all timing scenarios from the configuration.
|
|
432
464
|
|
|
@@ -450,13 +482,13 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
450
482
|
"""
|
|
451
483
|
if scenario is None:
|
|
452
484
|
scenarios = {}
|
|
453
|
-
for name in self.getkeys():
|
|
454
|
-
scenarios[name] = self.get(name, field="schema")
|
|
485
|
+
for name in self.getkeys("scenario"):
|
|
486
|
+
scenarios[name] = self.get("scenario", name, field="schema")
|
|
455
487
|
return scenarios
|
|
456
488
|
|
|
457
|
-
if not self.valid(scenario):
|
|
489
|
+
if not self.valid("scenario", scenario):
|
|
458
490
|
raise LookupError(f"{scenario} is not defined")
|
|
459
|
-
return self.get(scenario, field="schema")
|
|
491
|
+
return self.get("scenario", scenario, field="schema")
|
|
460
492
|
|
|
461
493
|
def make_scenario(self, scenario: str) -> ASICTimingScenarioSchema:
|
|
462
494
|
"""
|
|
@@ -483,13 +515,42 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
483
515
|
if not scenario:
|
|
484
516
|
raise ValueError("scenario name is required")
|
|
485
517
|
|
|
486
|
-
if self.valid(scenario):
|
|
518
|
+
if self.valid("scenario", scenario):
|
|
487
519
|
raise LookupError(f"{scenario} scenario already exists")
|
|
488
520
|
|
|
489
521
|
scenarioobj = ASICTimingScenarioSchema(scenario)
|
|
490
522
|
self.add_scenario(scenarioobj)
|
|
491
523
|
return scenarioobj
|
|
492
524
|
|
|
525
|
+
def copy_scenario(self, scenario: str, name: str, insert: bool = True) \
|
|
526
|
+
-> ASICTimingScenarioSchema:
|
|
527
|
+
"""
|
|
528
|
+
Copies an existing timing scenario, renames it, and optionally adds it to the design.
|
|
529
|
+
|
|
530
|
+
This method retrieves the scenario identified by ``scenario``, creates a
|
|
531
|
+
deep copy of it, and renames the copy to ``name``. If ``insert`` is True,
|
|
532
|
+
the new scenario is immediately added to the configuration.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
scenario (str): The name of the existing scenario to be copied.
|
|
536
|
+
name (str): The name to assign to the new copied scenario.
|
|
537
|
+
insert (bool, optional): Whether to add the newly created scenario
|
|
538
|
+
to the configuration. Defaults to True.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
ASICTimingScenarioSchema: The newly created copy of the scenario.
|
|
542
|
+
|
|
543
|
+
Raises:
|
|
544
|
+
LookupError: If the source scenario specified by ``scenario`` does not exist.
|
|
545
|
+
"""
|
|
546
|
+
constraint = EditableSchema(self.get_scenario(scenario)).copy()
|
|
547
|
+
EditableSchema(constraint).rename(name)
|
|
548
|
+
if insert:
|
|
549
|
+
if self.valid("scenario", name):
|
|
550
|
+
raise ValueError(f"{name} already exists")
|
|
551
|
+
self.add_scenario(constraint)
|
|
552
|
+
return constraint
|
|
553
|
+
|
|
493
554
|
def remove_scenario(self, scenario: str) -> bool:
|
|
494
555
|
"""
|
|
495
556
|
Removes a timing scenario from the design configuration.
|
|
@@ -511,8 +572,170 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
511
572
|
if not scenario:
|
|
512
573
|
raise ValueError("scenario name is required")
|
|
513
574
|
|
|
514
|
-
if not self.valid(scenario):
|
|
575
|
+
if not self.valid("scenario", scenario):
|
|
576
|
+
return False
|
|
577
|
+
|
|
578
|
+
EditableSchema(self).remove("scenario", scenario)
|
|
579
|
+
return True
|
|
580
|
+
|
|
581
|
+
def add_mode(self, mode: TimingModeSchema):
|
|
582
|
+
"""
|
|
583
|
+
Adds a timing mode to the design configuration.
|
|
584
|
+
|
|
585
|
+
This method is responsible for incorporating a new or updated timing mode
|
|
586
|
+
into the system's configuration. If a mode with the same name already
|
|
587
|
+
exists, it will be overwritten (`clobber=True`).
|
|
588
|
+
|
|
589
|
+
Args:
|
|
590
|
+
mode: The :class:`TimingModeSchema` object representing the timing mode
|
|
591
|
+
to add. This object must have a valid name defined via its `name()` method.
|
|
592
|
+
|
|
593
|
+
Raises:
|
|
594
|
+
TypeError: If the provided `mode` argument is not an instance of
|
|
595
|
+
:class:`TimingModeSchema`.
|
|
596
|
+
ValueError: If the `mode` object's `name()` method returns None, indicating
|
|
597
|
+
that the mode does not have a defined name.
|
|
598
|
+
"""
|
|
599
|
+
if not isinstance(mode, TimingModeSchema):
|
|
600
|
+
raise TypeError("mode must be a timing mode object")
|
|
601
|
+
|
|
602
|
+
if mode.name is None:
|
|
603
|
+
raise ValueError("mode must have a name")
|
|
604
|
+
|
|
605
|
+
EditableSchema(self).insert("mode", mode.name, mode, clobber=True)
|
|
606
|
+
|
|
607
|
+
def get_mode(self, mode: Optional[str] = None) \
|
|
608
|
+
-> Union[TimingModeSchema, Dict[str, TimingModeSchema]]:
|
|
609
|
+
"""
|
|
610
|
+
Retrieves one or all timing modes from the configuration.
|
|
611
|
+
|
|
612
|
+
This method provides flexibility to fetch either a specific timing mode
|
|
613
|
+
by its name or a collection of all currently defined modes.
|
|
614
|
+
|
|
615
|
+
Args:
|
|
616
|
+
mode (str, optional): The name (string) of the specific timing mode to retrieve.
|
|
617
|
+
If this argument is omitted or set to None, the method will
|
|
618
|
+
return a dictionary containing all available timing modes.
|
|
619
|
+
|
|
620
|
+
Returns:
|
|
621
|
+
If `mode` is provided: The :class:`TimingModeSchema` object corresponding
|
|
622
|
+
to the specified mode name.
|
|
623
|
+
If `mode` is None: A dictionary where keys are mode names (str) and
|
|
624
|
+
values are their respective :class:`TimingModeSchema` objects.
|
|
625
|
+
|
|
626
|
+
Raises:
|
|
627
|
+
LookupError: If a specific `mode` name is provided but no mode with
|
|
628
|
+
that name is found in the configuration.
|
|
629
|
+
"""
|
|
630
|
+
if mode is None:
|
|
631
|
+
modes = {}
|
|
632
|
+
for name in self.getkeys("mode"):
|
|
633
|
+
modes[name] = self.get("mode", name, field="schema")
|
|
634
|
+
return modes
|
|
635
|
+
|
|
636
|
+
if not self.valid("mode", mode):
|
|
637
|
+
raise LookupError(f"{mode} is not defined")
|
|
638
|
+
return self.get("mode", mode, field="schema")
|
|
639
|
+
|
|
640
|
+
def make_mode(self, mode: str) -> TimingModeSchema:
|
|
641
|
+
"""
|
|
642
|
+
Creates and adds a new timing mode with the specified name.
|
|
643
|
+
|
|
644
|
+
This method initializes a new :class:`TimingModeSchema` object with the given
|
|
645
|
+
name and immediately adds it to the constraint configuration. It ensures that
|
|
646
|
+
a mode with the same name does not already exist, preventing accidental
|
|
647
|
+
overwrites.
|
|
648
|
+
|
|
649
|
+
Args:
|
|
650
|
+
mode (str): The name for the new timing mode. This name must be
|
|
651
|
+
a non-empty string and unique within the current configuration.
|
|
652
|
+
|
|
653
|
+
Returns:
|
|
654
|
+
:class:`TimingModeSchema`: The newly created :class:`TimingModeSchema`
|
|
655
|
+
object.
|
|
656
|
+
|
|
657
|
+
Raises:
|
|
658
|
+
ValueError: If the provided `mode` name is empty or None.
|
|
659
|
+
LookupError: If a mode with the specified `mode` name already exists
|
|
660
|
+
in the configuration.
|
|
661
|
+
"""
|
|
662
|
+
if not mode:
|
|
663
|
+
raise ValueError("mode name is required")
|
|
664
|
+
|
|
665
|
+
if self.valid("mode", mode):
|
|
666
|
+
raise LookupError(f"{mode} mode already exists")
|
|
667
|
+
|
|
668
|
+
modeobj = TimingModeSchema(mode)
|
|
669
|
+
self.add_mode(modeobj)
|
|
670
|
+
return modeobj
|
|
671
|
+
|
|
672
|
+
def copy_mode(self, mode: str, name: str, insert: bool = True) \
|
|
673
|
+
-> TimingModeSchema:
|
|
674
|
+
"""
|
|
675
|
+
Copies an existing timing mode, renames it, and optionally adds it to the design.
|
|
676
|
+
|
|
677
|
+
This method retrieves the mode identified by ``mode``, creates a
|
|
678
|
+
deep copy of it, and renames the copy to ``name``. If ``insert`` is True,
|
|
679
|
+
the new mode is immediately added to the configuration.
|
|
680
|
+
|
|
681
|
+
Args:
|
|
682
|
+
mode (str): The name of the existing mode to be copied.
|
|
683
|
+
name (str): The name to assign to the new copied mode.
|
|
684
|
+
insert (bool, optional): Whether to add the newly created mode
|
|
685
|
+
to the configuration. Defaults to True.
|
|
686
|
+
|
|
687
|
+
Returns:
|
|
688
|
+
TimingModeSchema: The newly created copy of the mode.
|
|
689
|
+
|
|
690
|
+
Raises:
|
|
691
|
+
LookupError: If the source mode specified by ``mode`` does not exist.
|
|
692
|
+
"""
|
|
693
|
+
newmode = EditableSchema(self.get_mode(mode)).copy()
|
|
694
|
+
EditableSchema(newmode).rename(name)
|
|
695
|
+
if insert:
|
|
696
|
+
if self.valid("mode", name):
|
|
697
|
+
raise ValueError(f"{name} already exists")
|
|
698
|
+
self.add_mode(newmode)
|
|
699
|
+
return newmode
|
|
700
|
+
|
|
701
|
+
def remove_mode(self, mode: str) -> bool:
|
|
702
|
+
"""
|
|
703
|
+
Removes a timing mode from the design configuration.
|
|
704
|
+
|
|
705
|
+
This method deletes the specified timing mode from the system's
|
|
706
|
+
configuration.
|
|
707
|
+
|
|
708
|
+
Args:
|
|
709
|
+
mode (str): The name of the timing mode to remove.
|
|
710
|
+
This name must be a non-empty string.
|
|
711
|
+
|
|
712
|
+
Returns:
|
|
713
|
+
bool: True if the mode was successfully removed, False if no
|
|
714
|
+
mode with the given name was found.
|
|
715
|
+
|
|
716
|
+
Raises:
|
|
717
|
+
ValueError: If the provided `mode` name is empty or None.
|
|
718
|
+
"""
|
|
719
|
+
if not mode:
|
|
720
|
+
raise ValueError("mode name is required")
|
|
721
|
+
|
|
722
|
+
if not self.valid("mode", mode):
|
|
515
723
|
return False
|
|
516
724
|
|
|
517
|
-
EditableSchema(self).remove(
|
|
725
|
+
EditableSchema(self).remove("mode", mode)
|
|
518
726
|
return True
|
|
727
|
+
|
|
728
|
+
def _from_dict(self, manifest: Dict,
|
|
729
|
+
keypath: Union[List[str], Tuple[str, ...]],
|
|
730
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
731
|
+
lazyload: LazyLoad = LazyLoad.ON) \
|
|
732
|
+
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
733
|
+
if version and version < (0, 53, 0):
|
|
734
|
+
manifest.pop("__meta__", None)
|
|
735
|
+
manifest = {
|
|
736
|
+
"scenario": manifest,
|
|
737
|
+
"mode": self.getdict("mode")
|
|
738
|
+
}
|
|
739
|
+
lazyload = LazyLoad.OFF
|
|
740
|
+
|
|
741
|
+
return super()._from_dict(manifest, keypath, version, lazyload)
|