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,7 +1,9 @@
|
|
|
1
|
-
from typing import Union
|
|
1
|
+
from typing import List, Set, Tuple, Union, Optional, Dict
|
|
2
2
|
|
|
3
3
|
from siliconcompiler.schema import BaseSchema, NamedSchema, EditableSchema, Parameter, \
|
|
4
4
|
PerNode, Scope
|
|
5
|
+
from siliconcompiler.constraints.timing_mode import TimingModeSchema
|
|
6
|
+
from siliconcompiler.schema.baseschema import LazyLoad
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class FPGATimingScenarioSchema(NamedSchema):
|
|
@@ -12,7 +14,7 @@ class FPGATimingScenarioSchema(NamedSchema):
|
|
|
12
14
|
scenario and operating mode.
|
|
13
15
|
"""
|
|
14
16
|
|
|
15
|
-
def __init__(self, name: str = None):
|
|
17
|
+
def __init__(self, name: Optional[str] = None):
|
|
16
18
|
super().__init__()
|
|
17
19
|
self.set_name(name)
|
|
18
20
|
|
|
@@ -31,7 +33,7 @@ class FPGATimingScenarioSchema(NamedSchema):
|
|
|
31
33
|
|
|
32
34
|
def set_mode(self,
|
|
33
35
|
mode: str,
|
|
34
|
-
step: str = None, index: Union[str, int] = None):
|
|
36
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
35
37
|
"""
|
|
36
38
|
Sets the operational mode for the design.
|
|
37
39
|
|
|
@@ -42,8 +44,7 @@ class FPGATimingScenarioSchema(NamedSchema):
|
|
|
42
44
|
"""
|
|
43
45
|
return self.set("mode", mode, step=step, index=index)
|
|
44
46
|
|
|
45
|
-
def get_mode(self,
|
|
46
|
-
step: str = None, index: Union[str, int] = None) -> str:
|
|
47
|
+
def get_mode(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) -> str:
|
|
47
48
|
"""
|
|
48
49
|
Gets the operational mode currently set for the design.
|
|
49
50
|
|
|
@@ -70,7 +71,8 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
70
71
|
def __init__(self):
|
|
71
72
|
super().__init__()
|
|
72
73
|
|
|
73
|
-
EditableSchema(self).insert("default", FPGATimingScenarioSchema())
|
|
74
|
+
EditableSchema(self).insert("scenario", "default", FPGATimingScenarioSchema())
|
|
75
|
+
EditableSchema(self).insert("mode", "default", TimingModeSchema())
|
|
74
76
|
|
|
75
77
|
def add_scenario(self, scenario: FPGATimingScenarioSchema):
|
|
76
78
|
"""
|
|
@@ -96,9 +98,10 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
96
98
|
if scenario.name is None:
|
|
97
99
|
raise ValueError("scenario must have a name")
|
|
98
100
|
|
|
99
|
-
EditableSchema(self).insert(scenario.name, scenario, clobber=True)
|
|
101
|
+
EditableSchema(self).insert("scenario", scenario.name, scenario, clobber=True)
|
|
100
102
|
|
|
101
|
-
def get_scenario(self, scenario: str = None)
|
|
103
|
+
def get_scenario(self, scenario: Optional[str] = None) \
|
|
104
|
+
-> Union[FPGATimingScenarioSchema, Dict[str, FPGATimingScenarioSchema]]:
|
|
102
105
|
"""
|
|
103
106
|
Retrieves one or all timing scenarios from the configuration.
|
|
104
107
|
|
|
@@ -107,8 +110,8 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
107
110
|
|
|
108
111
|
Args:
|
|
109
112
|
scenario (str, optional): The name (string) of the specific timing scenario to retrieve.
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
If this argument is omitted or set to None, the method will
|
|
114
|
+
return a dictionary containing all available timing scenarios.
|
|
112
115
|
|
|
113
116
|
Returns:
|
|
114
117
|
If `scenario` is provided: The :class:`FPGATimingScenarioSchema` object corresponding
|
|
@@ -122,13 +125,13 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
122
125
|
"""
|
|
123
126
|
if scenario is None:
|
|
124
127
|
scenarios = {}
|
|
125
|
-
for
|
|
126
|
-
scenarios[
|
|
128
|
+
for name in self.getkeys("scenario"):
|
|
129
|
+
scenarios[name] = self.get("scenario", name, field="schema")
|
|
127
130
|
return scenarios
|
|
128
131
|
|
|
129
|
-
if not self.valid(scenario):
|
|
132
|
+
if not self.valid("scenario", scenario):
|
|
130
133
|
raise LookupError(f"{scenario} is not defined")
|
|
131
|
-
return self.get(scenario, field="schema")
|
|
134
|
+
return self.get("scenario", scenario, field="schema")
|
|
132
135
|
|
|
133
136
|
def make_scenario(self, scenario: str) -> FPGATimingScenarioSchema:
|
|
134
137
|
"""
|
|
@@ -144,7 +147,7 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
144
147
|
a non-empty string and unique within the current configuration.
|
|
145
148
|
|
|
146
149
|
Returns:
|
|
147
|
-
:class
|
|
150
|
+
:class:`FPGATimingScenarioSchema`: The newly created :class:`FPGATimingScenarioSchema`
|
|
148
151
|
object.
|
|
149
152
|
|
|
150
153
|
Raises:
|
|
@@ -155,13 +158,42 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
155
158
|
if not scenario:
|
|
156
159
|
raise ValueError("scenario name is required")
|
|
157
160
|
|
|
158
|
-
if self.valid(scenario):
|
|
161
|
+
if self.valid("scenario", scenario):
|
|
159
162
|
raise LookupError(f"{scenario} scenario already exists")
|
|
160
163
|
|
|
161
164
|
scenarioobj = FPGATimingScenarioSchema(scenario)
|
|
162
165
|
self.add_scenario(scenarioobj)
|
|
163
166
|
return scenarioobj
|
|
164
167
|
|
|
168
|
+
def copy_scenario(self, scenario: str, name: str, insert: bool = True) \
|
|
169
|
+
-> FPGATimingScenarioSchema:
|
|
170
|
+
"""
|
|
171
|
+
Copies an existing timing scenario, renames it, and optionally adds it to the design.
|
|
172
|
+
|
|
173
|
+
This method retrieves the scenario identified by ``scenario``, creates a
|
|
174
|
+
deep copy of it, and renames the copy to ``name``. If ``insert`` is True,
|
|
175
|
+
the new scenario is immediately added to the configuration.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
scenario (str): The name of the existing scenario to be copied.
|
|
179
|
+
name (str): The name to assign to the new copied scenario.
|
|
180
|
+
insert (bool, optional): Whether to add the newly created scenario
|
|
181
|
+
to the configuration. Defaults to True.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
FPGATimingScenarioSchema: The newly created copy of the scenario.
|
|
185
|
+
|
|
186
|
+
Raises:
|
|
187
|
+
LookupError: If the source scenario specified by ``scenario`` does not exist.
|
|
188
|
+
"""
|
|
189
|
+
constraint = EditableSchema(self.get_scenario(scenario)).copy()
|
|
190
|
+
EditableSchema(constraint).rename(name)
|
|
191
|
+
if insert:
|
|
192
|
+
if self.valid("scenario", name):
|
|
193
|
+
raise ValueError(f"{name} already exists")
|
|
194
|
+
self.add_scenario(constraint)
|
|
195
|
+
return constraint
|
|
196
|
+
|
|
165
197
|
def remove_scenario(self, scenario: str) -> bool:
|
|
166
198
|
"""
|
|
167
199
|
Removes a timing scenario from the design configuration.
|
|
@@ -183,8 +215,170 @@ class FPGATimingConstraintSchema(BaseSchema):
|
|
|
183
215
|
if not scenario:
|
|
184
216
|
raise ValueError("scenario name is required")
|
|
185
217
|
|
|
186
|
-
if not self.valid(scenario):
|
|
218
|
+
if not self.valid("scenario", scenario):
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
EditableSchema(self).remove("scenario", scenario)
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
def add_mode(self, mode: TimingModeSchema):
|
|
225
|
+
"""
|
|
226
|
+
Adds a timing mode to the design configuration.
|
|
227
|
+
|
|
228
|
+
This method is responsible for incorporating a new or updated timing mode
|
|
229
|
+
into the system's configuration. If a mode with the same name already
|
|
230
|
+
exists, it will be overwritten (`clobber=True`).
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
mode: The :class:`TimingModeSchema` object representing the timing mode
|
|
234
|
+
to add. This object must have a valid name defined via its `name()` method.
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
TypeError: If the provided `mode` argument is not an instance of
|
|
238
|
+
:class:`TimingModeSchema`.
|
|
239
|
+
ValueError: If the `mode` object's `name()` method returns None, indicating
|
|
240
|
+
that the mode does not have a defined name.
|
|
241
|
+
"""
|
|
242
|
+
if not isinstance(mode, TimingModeSchema):
|
|
243
|
+
raise TypeError("mode must be a timing mode object")
|
|
244
|
+
|
|
245
|
+
if mode.name is None:
|
|
246
|
+
raise ValueError("mode must have a name")
|
|
247
|
+
|
|
248
|
+
EditableSchema(self).insert("mode", mode.name, mode, clobber=True)
|
|
249
|
+
|
|
250
|
+
def get_mode(self, mode: Optional[str] = None) \
|
|
251
|
+
-> Union[TimingModeSchema, Dict[str, TimingModeSchema]]:
|
|
252
|
+
"""
|
|
253
|
+
Retrieves one or all timing modes from the configuration.
|
|
254
|
+
|
|
255
|
+
This method provides flexibility to fetch either a specific timing mode
|
|
256
|
+
by its name or a collection of all currently defined modes.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
mode (str, optional): The name (string) of the specific timing mode to retrieve.
|
|
260
|
+
If this argument is omitted or set to None, the method will
|
|
261
|
+
return a dictionary containing all available timing modes.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
If `mode` is provided: The :class:`TimingModeSchema` object corresponding
|
|
265
|
+
to the specified mode name.
|
|
266
|
+
If `mode` is None: A dictionary where keys are mode names (str) and
|
|
267
|
+
values are their respective :class:`TimingModeSchema` objects.
|
|
268
|
+
|
|
269
|
+
Raises:
|
|
270
|
+
LookupError: If a specific `mode` name is provided but no mode with
|
|
271
|
+
that name is found in the configuration.
|
|
272
|
+
"""
|
|
273
|
+
if mode is None:
|
|
274
|
+
modes = {}
|
|
275
|
+
for name in self.getkeys("mode"):
|
|
276
|
+
modes[name] = self.get("mode", name, field="schema")
|
|
277
|
+
return modes
|
|
278
|
+
|
|
279
|
+
if not self.valid("mode", mode):
|
|
280
|
+
raise LookupError(f"{mode} is not defined")
|
|
281
|
+
return self.get("mode", mode, field="schema")
|
|
282
|
+
|
|
283
|
+
def make_mode(self, mode: str) -> TimingModeSchema:
|
|
284
|
+
"""
|
|
285
|
+
Creates and adds a new timing mode with the specified name.
|
|
286
|
+
|
|
287
|
+
This method initializes a new :class:`TimingModeSchema` object with the given
|
|
288
|
+
name and immediately adds it to the constraint configuration. It ensures that
|
|
289
|
+
a mode with the same name does not already exist, preventing accidental
|
|
290
|
+
overwrites.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
mode (str): The name for the new timing mode. This name must be
|
|
294
|
+
a non-empty string and unique within the current configuration.
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
:class:`TimingModeSchema`: The newly created :class:`TimingModeSchema`
|
|
298
|
+
object.
|
|
299
|
+
|
|
300
|
+
Raises:
|
|
301
|
+
ValueError: If the provided `mode` name is empty or None.
|
|
302
|
+
LookupError: If a mode with the specified `mode` name already exists
|
|
303
|
+
in the configuration.
|
|
304
|
+
"""
|
|
305
|
+
if not mode:
|
|
306
|
+
raise ValueError("mode name is required")
|
|
307
|
+
|
|
308
|
+
if self.valid("mode", mode):
|
|
309
|
+
raise LookupError(f"{mode} mode already exists")
|
|
310
|
+
|
|
311
|
+
modeobj = TimingModeSchema(mode)
|
|
312
|
+
self.add_mode(modeobj)
|
|
313
|
+
return modeobj
|
|
314
|
+
|
|
315
|
+
def copy_mode(self, mode: str, name: str, insert: bool = True) \
|
|
316
|
+
-> TimingModeSchema:
|
|
317
|
+
"""
|
|
318
|
+
Copies an existing timing mode, renames it, and optionally adds it to the design.
|
|
319
|
+
|
|
320
|
+
This method retrieves the mode identified by ``mode``, creates a
|
|
321
|
+
deep copy of it, and renames the copy to ``name``. If ``insert`` is True,
|
|
322
|
+
the new mode is immediately added to the configuration.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
mode (str): The name of the existing mode to be copied.
|
|
326
|
+
name (str): The name to assign to the new copied mode.
|
|
327
|
+
insert (bool, optional): Whether to add the newly created mode
|
|
328
|
+
to the configuration. Defaults to True.
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
TimingModeSchema: The newly created copy of the mode.
|
|
332
|
+
|
|
333
|
+
Raises:
|
|
334
|
+
LookupError: If the source mode specified by ``mode`` does not exist.
|
|
335
|
+
"""
|
|
336
|
+
newmode = EditableSchema(self.get_mode(mode)).copy()
|
|
337
|
+
EditableSchema(newmode).rename(name)
|
|
338
|
+
if insert:
|
|
339
|
+
if self.valid("mode", name):
|
|
340
|
+
raise ValueError(f"{name} already exists")
|
|
341
|
+
self.add_mode(newmode)
|
|
342
|
+
return newmode
|
|
343
|
+
|
|
344
|
+
def remove_mode(self, mode: str) -> bool:
|
|
345
|
+
"""
|
|
346
|
+
Removes a timing mode from the design configuration.
|
|
347
|
+
|
|
348
|
+
This method deletes the specified timing mode from the system's
|
|
349
|
+
configuration.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
mode (str): The name of the timing mode to remove.
|
|
353
|
+
This name must be a non-empty string.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
bool: True if the mode was successfully removed, False if no
|
|
357
|
+
mode with the given name was found.
|
|
358
|
+
|
|
359
|
+
Raises:
|
|
360
|
+
ValueError: If the provided `mode` name is empty or None.
|
|
361
|
+
"""
|
|
362
|
+
if not mode:
|
|
363
|
+
raise ValueError("mode name is required")
|
|
364
|
+
|
|
365
|
+
if not self.valid("mode", mode):
|
|
187
366
|
return False
|
|
188
367
|
|
|
189
|
-
EditableSchema(self).remove(
|
|
368
|
+
EditableSchema(self).remove("mode", mode)
|
|
190
369
|
return True
|
|
370
|
+
|
|
371
|
+
def _from_dict(self, manifest: Dict,
|
|
372
|
+
keypath: Union[List[str], Tuple[str, ...]],
|
|
373
|
+
version: Optional[Tuple[int, ...]] = None,
|
|
374
|
+
lazyload: LazyLoad = LazyLoad.ON) \
|
|
375
|
+
-> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
|
|
376
|
+
if version and version < (0, 53, 0):
|
|
377
|
+
manifest.pop("__meta__", None)
|
|
378
|
+
manifest = {
|
|
379
|
+
"scenario": manifest,
|
|
380
|
+
"mode": self.getdict("mode")
|
|
381
|
+
}
|
|
382
|
+
lazyload = LazyLoad.OFF
|
|
383
|
+
|
|
384
|
+
return super()._from_dict(manifest, keypath, version, lazyload)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from typing import Union, List, Tuple, Optional
|
|
2
|
+
|
|
3
|
+
from siliconcompiler.schema import NamedSchema, EditableSchema, Parameter, \
|
|
4
|
+
PerNode, Scope
|
|
5
|
+
from siliconcompiler import Design
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TimingModeSchema(NamedSchema):
|
|
9
|
+
"""
|
|
10
|
+
Represents a single timing mode for design constraints.
|
|
11
|
+
|
|
12
|
+
This class encapsulates the SDC filesets used for a specific timing mode.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, name: Optional[str] = None):
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.set_name(name)
|
|
18
|
+
|
|
19
|
+
schema = EditableSchema(self)
|
|
20
|
+
schema.insert(
|
|
21
|
+
'sdcfileset',
|
|
22
|
+
Parameter(
|
|
23
|
+
'[(str,str)]',
|
|
24
|
+
pernode=PerNode.OPTIONAL,
|
|
25
|
+
scope=Scope.GLOBAL,
|
|
26
|
+
shorthelp="Constraint: SDC files",
|
|
27
|
+
switch="-constraint_timing_file 'scenario <file>'",
|
|
28
|
+
example=["api: mode.set('constraint', 'timing', 'worst', 'file', 'hello.sdc')"],
|
|
29
|
+
help="""List of timing constraint sets files to use for the scenario. The
|
|
30
|
+
values are combined with any constraints specified by the design
|
|
31
|
+
'constraint' parameter. If no constraints are found, a default
|
|
32
|
+
constraint file is used based on the clock definitions."""))
|
|
33
|
+
|
|
34
|
+
def add_sdcfileset(self,
|
|
35
|
+
design: Union[Design, str],
|
|
36
|
+
fileset: str,
|
|
37
|
+
clobber: bool = False,
|
|
38
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
39
|
+
"""
|
|
40
|
+
Adds an SDC fileset for a given design.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
design (:class:`Design` or str): The design object or the name of the design to
|
|
44
|
+
associate the fileset with.
|
|
45
|
+
fileset (str): The name of the SDC fileset to add.
|
|
46
|
+
clobber (bool): If True, existing SDC filesets for the design at the specified
|
|
47
|
+
step/index will be overwritten.
|
|
48
|
+
If False (default), the SDC fileset will be added.
|
|
49
|
+
step (str, optional): step name.
|
|
50
|
+
index (str, optional): index name.
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
TypeError: If `design` is not a Design object or a string, or if `fileset` is not
|
|
54
|
+
a string.
|
|
55
|
+
"""
|
|
56
|
+
if isinstance(design, Design):
|
|
57
|
+
design = design.name
|
|
58
|
+
|
|
59
|
+
if not isinstance(design, str):
|
|
60
|
+
raise TypeError("design must be a design object or string")
|
|
61
|
+
|
|
62
|
+
if not isinstance(fileset, str):
|
|
63
|
+
raise TypeError("fileset must be a string")
|
|
64
|
+
|
|
65
|
+
if clobber:
|
|
66
|
+
return self.set("sdcfileset", (design, fileset), step=step, index=index)
|
|
67
|
+
else:
|
|
68
|
+
return self.add("sdcfileset", (design, fileset), step=step, index=index)
|
|
69
|
+
|
|
70
|
+
def get_sdcfileset(self, step: Optional[str] = None, index: Optional[Union[str, int]] = None) \
|
|
71
|
+
-> List[Tuple[str, str]]:
|
|
72
|
+
"""
|
|
73
|
+
Gets the list of SDC filesets.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
step (str, optional): step name.
|
|
77
|
+
index (str, optional): index name.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
A list of tuples, where each tuple contains the design name and the SDC fileset name.
|
|
81
|
+
"""
|
|
82
|
+
return self.get("sdcfileset", step=step, index=index)
|
|
@@ -4,10 +4,27 @@ if [ "${BASH_SOURCE[0]}" != "$0" ]; then
|
|
|
4
4
|
return
|
|
5
5
|
fi
|
|
6
6
|
|
|
7
|
+
__print_help() {
|
|
8
|
+
# Print help information for this file
|
|
9
|
+
echo "Usage: $0"
|
|
10
|
+
echo " Options:"
|
|
11
|
+
echo " --which print which executable would be used"
|
|
12
|
+
echo " --version print the version of the executable, if supported"
|
|
13
|
+
echo " --directory print the execution directory"
|
|
14
|
+
echo " --command print the execution command"
|
|
15
|
+
echo " --skipcd do not change directory into replay directory"
|
|
16
|
+
echo " --skipexports do not export environmental variables"
|
|
17
|
+
echo " --cmdprefix <cmd> prefix to add to the replay command, such as gdb"
|
|
18
|
+
echo " --cmdarg <args> prefix to add to the replay command, such as -gui"
|
|
19
|
+
echo " --node execute entire node"
|
|
20
|
+
echo " -h,--help print this help"
|
|
21
|
+
}
|
|
22
|
+
|
|
7
23
|
# Parse replay arguments
|
|
8
24
|
CD_WORK="{{ work_dir }}"
|
|
9
25
|
PRINT=""
|
|
10
26
|
CMDPREFIX=""
|
|
27
|
+
CMDARGS=""
|
|
11
28
|
SKIPEXPORT=0
|
|
12
29
|
DONODE={{ node_only }}
|
|
13
30
|
while [[ $# -gt 0 ]]; do
|
|
@@ -41,27 +58,22 @@ while [[ $# -gt 0 ]]; do
|
|
|
41
58
|
shift
|
|
42
59
|
shift
|
|
43
60
|
;;
|
|
61
|
+
--cmdarg)
|
|
62
|
+
CMDARGS="$2"
|
|
63
|
+
shift
|
|
64
|
+
shift
|
|
65
|
+
;;
|
|
44
66
|
--node)
|
|
45
67
|
DONODE=1
|
|
46
68
|
shift
|
|
47
|
-
shift
|
|
48
69
|
;;
|
|
49
70
|
-h|--help)
|
|
50
|
-
|
|
51
|
-
echo " Options:"
|
|
52
|
-
echo " --which print which executable would be used"
|
|
53
|
-
echo " --version print the version of the executable, if supported"
|
|
54
|
-
echo " --directory print the execution directory"
|
|
55
|
-
echo " --command print the execution command"
|
|
56
|
-
echo " --skipcd do not change directory into replay directory"
|
|
57
|
-
echo " --skipexports do not export environmental variables"
|
|
58
|
-
echo " --cmdprefix <cmd> prefix to add to the replay command, such as dgb"
|
|
59
|
-
echo " --node execute entire node"
|
|
60
|
-
echo " -h,--help print this help"
|
|
71
|
+
__print_help
|
|
61
72
|
exit 0
|
|
62
73
|
;;
|
|
63
74
|
*)
|
|
64
75
|
echo "Unknown option $1"
|
|
76
|
+
__print_help
|
|
65
77
|
exit 1
|
|
66
78
|
;;
|
|
67
79
|
esac
|
|
@@ -105,5 +117,6 @@ python3 -m siliconcompiler.scheduler.run_node \
|
|
|
105
117
|
{% if cmds|length > 0 %}else
|
|
106
118
|
# Command execution
|
|
107
119
|
$CMDPREFIX \{% for cmd in cmds %}
|
|
108
|
-
{% if not loop.first %} {% endif %}{{ cmd }}
|
|
109
|
-
{% endif %}
|
|
120
|
+
{% if not loop.first %} {% endif %}{{ cmd }} \{% endfor %}
|
|
121
|
+
{% endif %} ${CMDARGS}
|
|
122
|
+
fi
|
|
@@ -17,12 +17,6 @@ proc sc_root {} {
|
|
|
17
17
|
|
|
18
18
|
{% include 'tools/_common/tcl/sc_schema_access.tcl' %}
|
|
19
19
|
|
|
20
|
-
# Redefine
|
|
21
|
-
proc _sc_cfg_get_debug { args } {
|
|
22
|
-
{% if record_access %}puts "{{ record_access_id }} [join $args ,]"{% endif %}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
20
|
#############################################
|
|
27
21
|
# Tool variables
|
|
28
22
|
#############################################
|