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.
Files changed (96) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_issue.py +18 -2
  3. siliconcompiler/checklist.py +2 -1
  4. siliconcompiler/constraints/__init__.py +4 -1
  5. siliconcompiler/constraints/asic_component.py +49 -11
  6. siliconcompiler/constraints/asic_floorplan.py +23 -21
  7. siliconcompiler/constraints/asic_pins.py +55 -17
  8. siliconcompiler/constraints/asic_timing.py +280 -57
  9. siliconcompiler/constraints/fpga_timing.py +212 -18
  10. siliconcompiler/constraints/timing_mode.py +82 -0
  11. siliconcompiler/data/templates/replay/replay.sh.j2 +27 -14
  12. siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
  13. siliconcompiler/flowgraph.py +95 -42
  14. siliconcompiler/flows/generate_openroad_rcx.py +2 -2
  15. siliconcompiler/flows/highresscreenshotflow.py +37 -0
  16. siliconcompiler/library.py +2 -1
  17. siliconcompiler/package/__init__.py +56 -51
  18. siliconcompiler/project.py +13 -2
  19. siliconcompiler/scheduler/docker.py +24 -25
  20. siliconcompiler/scheduler/scheduler.py +143 -100
  21. siliconcompiler/scheduler/schedulernode.py +138 -22
  22. siliconcompiler/scheduler/slurm.py +120 -35
  23. siliconcompiler/scheduler/taskscheduler.py +19 -23
  24. siliconcompiler/schema/_metadata.py +1 -1
  25. siliconcompiler/schema/editableschema.py +29 -0
  26. siliconcompiler/schema/namedschema.py +2 -4
  27. siliconcompiler/schema/parametervalue.py +14 -2
  28. siliconcompiler/schema_support/cmdlineschema.py +0 -3
  29. siliconcompiler/schema_support/dependencyschema.py +0 -6
  30. siliconcompiler/schema_support/option.py +82 -1
  31. siliconcompiler/schema_support/pathschema.py +7 -13
  32. siliconcompiler/schema_support/record.py +4 -3
  33. siliconcompiler/tool.py +105 -52
  34. siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
  35. siliconcompiler/tools/keplerformal/__init__.py +7 -0
  36. siliconcompiler/tools/keplerformal/lec.py +112 -0
  37. siliconcompiler/tools/klayout/__init__.py +3 -0
  38. siliconcompiler/tools/klayout/screenshot.py +66 -1
  39. siliconcompiler/tools/klayout/scripts/klayout_convert_drc_db.py +1 -0
  40. siliconcompiler/tools/klayout/scripts/klayout_export.py +11 -40
  41. siliconcompiler/tools/klayout/scripts/klayout_operations.py +1 -0
  42. siliconcompiler/tools/klayout/scripts/klayout_show.py +5 -4
  43. siliconcompiler/tools/klayout/scripts/klayout_utils.py +16 -5
  44. siliconcompiler/tools/montage/tile.py +26 -12
  45. siliconcompiler/tools/openroad/__init__.py +27 -1
  46. siliconcompiler/tools/openroad/_apr.py +107 -14
  47. siliconcompiler/tools/openroad/clock_tree_synthesis.py +1 -0
  48. siliconcompiler/tools/openroad/global_placement.py +1 -0
  49. siliconcompiler/tools/openroad/init_floorplan.py +119 -7
  50. siliconcompiler/tools/openroad/power_grid_analysis.py +174 -0
  51. siliconcompiler/tools/openroad/repair_design.py +1 -0
  52. siliconcompiler/tools/openroad/repair_timing.py +1 -0
  53. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +1 -1
  54. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +91 -18
  55. siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +148 -0
  56. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -1
  57. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +8 -10
  58. siliconcompiler/tools/openroad/scripts/common/procs.tcl +15 -6
  59. siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
  60. siliconcompiler/tools/openroad/scripts/common/reports.tcl +7 -4
  61. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
  62. siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
  63. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
  64. siliconcompiler/tools/openroad/scripts/rcx/sc_rcx_bench.tcl +2 -4
  65. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
  66. siliconcompiler/tools/openroad/write_data.py +2 -2
  67. siliconcompiler/tools/opensta/__init__.py +1 -1
  68. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
  69. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
  70. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +13 -10
  71. siliconcompiler/tools/opensta/timing.py +6 -2
  72. siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +11 -0
  73. siliconcompiler/tools/vivado/scripts/sc_place.tcl +11 -0
  74. siliconcompiler/tools/vivado/scripts/sc_route.tcl +11 -0
  75. siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +10 -0
  76. siliconcompiler/tools/vpr/__init__.py +28 -0
  77. siliconcompiler/tools/yosys/scripts/sc_screenshot.tcl +1 -1
  78. siliconcompiler/tools/yosys/scripts/sc_synth_asic.tcl +40 -4
  79. siliconcompiler/tools/yosys/scripts/sc_synth_fpga.tcl +15 -5
  80. siliconcompiler/tools/yosys/syn_asic.py +42 -0
  81. siliconcompiler/tools/yosys/syn_fpga.py +8 -0
  82. siliconcompiler/toolscripts/_tools.json +12 -7
  83. siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
  84. siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
  85. siliconcompiler/utils/__init__.py +243 -51
  86. siliconcompiler/utils/curation.py +89 -56
  87. siliconcompiler/utils/issue.py +6 -1
  88. siliconcompiler/utils/multiprocessing.py +46 -2
  89. siliconcompiler/utils/paths.py +21 -0
  90. siliconcompiler/utils/settings.py +162 -0
  91. {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/METADATA +5 -4
  92. {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/RECORD +96 -87
  93. {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/WHEEL +0 -0
  94. {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/entry_points.txt +0 -0
  95. {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/licenses/LICENSE +0 -0
  96. {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
- If this argument is omitted or set to None, the method will return
111
- a dictionary containing all available timing scenarios.
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 scenario in self.getkeys():
126
- scenarios[scenario] = self.get(scenario, field="schema")
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:FPGATimingScenarioSchema: The newly created :class:`FPGATimingScenarioSchema`
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(scenario)
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
- echo "Usage: $0"
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 }}{% if not loop.last %} \{% endif %}{% endfor %}
109
- {% endif %}fi
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
  #############################################