siliconcompiler 0.34.2__py3-none-any.whl → 0.34.3__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 (121) hide show
  1. siliconcompiler/__init__.py +12 -5
  2. siliconcompiler/__main__.py +1 -7
  3. siliconcompiler/_metadata.py +1 -1
  4. siliconcompiler/apps/_common.py +104 -23
  5. siliconcompiler/apps/sc.py +4 -8
  6. siliconcompiler/apps/sc_dashboard.py +6 -4
  7. siliconcompiler/apps/sc_install.py +10 -6
  8. siliconcompiler/apps/sc_issue.py +7 -5
  9. siliconcompiler/apps/sc_remote.py +1 -1
  10. siliconcompiler/apps/sc_server.py +9 -14
  11. siliconcompiler/apps/sc_show.py +6 -5
  12. siliconcompiler/apps/smake.py +130 -94
  13. siliconcompiler/apps/utils/replay.py +4 -7
  14. siliconcompiler/apps/utils/summarize.py +3 -5
  15. siliconcompiler/asic.py +420 -0
  16. siliconcompiler/checklist.py +25 -2
  17. siliconcompiler/cmdlineschema.py +534 -0
  18. siliconcompiler/constraints/asic_component.py +2 -2
  19. siliconcompiler/constraints/asic_pins.py +2 -2
  20. siliconcompiler/constraints/asic_timing.py +3 -3
  21. siliconcompiler/core.py +7 -32
  22. siliconcompiler/data/templates/tcl/manifest.tcl.j2 +8 -0
  23. siliconcompiler/dependencyschema.py +89 -31
  24. siliconcompiler/design.py +176 -207
  25. siliconcompiler/filesetschema.py +250 -0
  26. siliconcompiler/flowgraph.py +274 -95
  27. siliconcompiler/fpga.py +124 -1
  28. siliconcompiler/library.py +218 -20
  29. siliconcompiler/metric.py +233 -20
  30. siliconcompiler/package/__init__.py +271 -50
  31. siliconcompiler/package/git.py +92 -16
  32. siliconcompiler/package/github.py +108 -12
  33. siliconcompiler/package/https.py +79 -16
  34. siliconcompiler/packageschema.py +88 -7
  35. siliconcompiler/pathschema.py +31 -2
  36. siliconcompiler/pdk.py +566 -1
  37. siliconcompiler/project.py +1095 -94
  38. siliconcompiler/record.py +38 -1
  39. siliconcompiler/remote/__init__.py +5 -2
  40. siliconcompiler/remote/client.py +11 -6
  41. siliconcompiler/remote/schema.py +5 -23
  42. siliconcompiler/remote/server.py +41 -54
  43. siliconcompiler/report/__init__.py +3 -3
  44. siliconcompiler/report/dashboard/__init__.py +48 -14
  45. siliconcompiler/report/dashboard/cli/__init__.py +99 -21
  46. siliconcompiler/report/dashboard/cli/board.py +364 -179
  47. siliconcompiler/report/dashboard/web/__init__.py +90 -12
  48. siliconcompiler/report/dashboard/web/components/__init__.py +219 -240
  49. siliconcompiler/report/dashboard/web/components/flowgraph.py +49 -26
  50. siliconcompiler/report/dashboard/web/components/graph.py +139 -100
  51. siliconcompiler/report/dashboard/web/layouts/__init__.py +29 -1
  52. siliconcompiler/report/dashboard/web/layouts/_common.py +38 -2
  53. siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph.py +39 -26
  54. siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_node_tab.py +50 -50
  55. siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_sac_tabs.py +49 -46
  56. siliconcompiler/report/dashboard/web/state.py +141 -14
  57. siliconcompiler/report/dashboard/web/utils/__init__.py +79 -16
  58. siliconcompiler/report/dashboard/web/utils/file_utils.py +74 -11
  59. siliconcompiler/report/dashboard/web/viewer.py +25 -1
  60. siliconcompiler/report/report.py +5 -2
  61. siliconcompiler/report/summary_image.py +29 -11
  62. siliconcompiler/scheduler/__init__.py +9 -1
  63. siliconcompiler/scheduler/docker.py +79 -1
  64. siliconcompiler/scheduler/run_node.py +35 -19
  65. siliconcompiler/scheduler/scheduler.py +208 -24
  66. siliconcompiler/scheduler/schedulernode.py +372 -46
  67. siliconcompiler/scheduler/send_messages.py +77 -29
  68. siliconcompiler/scheduler/slurm.py +76 -12
  69. siliconcompiler/scheduler/taskscheduler.py +140 -20
  70. siliconcompiler/schema/__init__.py +0 -2
  71. siliconcompiler/schema/baseschema.py +194 -38
  72. siliconcompiler/schema/journal.py +7 -4
  73. siliconcompiler/schema/namedschema.py +16 -10
  74. siliconcompiler/schema/parameter.py +55 -9
  75. siliconcompiler/schema/parametervalue.py +60 -0
  76. siliconcompiler/schema/safeschema.py +25 -2
  77. siliconcompiler/schema/schema_cfg.py +5 -5
  78. siliconcompiler/schema/utils.py +2 -2
  79. siliconcompiler/schema_obj.py +20 -3
  80. siliconcompiler/tool.py +979 -302
  81. siliconcompiler/tools/bambu/__init__.py +41 -0
  82. siliconcompiler/tools/builtin/concatenate.py +2 -2
  83. siliconcompiler/tools/builtin/minimum.py +2 -1
  84. siliconcompiler/tools/builtin/mux.py +2 -1
  85. siliconcompiler/tools/builtin/nop.py +2 -1
  86. siliconcompiler/tools/builtin/verify.py +2 -1
  87. siliconcompiler/tools/klayout/__init__.py +95 -0
  88. siliconcompiler/tools/openroad/__init__.py +289 -0
  89. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -0
  90. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +7 -2
  91. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +8 -4
  92. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +9 -5
  93. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +5 -1
  94. siliconcompiler/tools/slang/__init__.py +1 -1
  95. siliconcompiler/tools/slang/elaborate.py +2 -1
  96. siliconcompiler/tools/vivado/scripts/sc_run.tcl +1 -1
  97. siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +8 -1
  98. siliconcompiler/tools/vivado/syn_fpga.py +6 -0
  99. siliconcompiler/tools/vivado/vivado.py +35 -2
  100. siliconcompiler/tools/vpr/__init__.py +150 -0
  101. siliconcompiler/tools/yosys/__init__.py +369 -1
  102. siliconcompiler/tools/yosys/scripts/procs.tcl +0 -1
  103. siliconcompiler/toolscripts/_tools.json +5 -10
  104. siliconcompiler/utils/__init__.py +66 -0
  105. siliconcompiler/utils/flowgraph.py +2 -2
  106. siliconcompiler/utils/issue.py +2 -1
  107. siliconcompiler/utils/logging.py +14 -0
  108. siliconcompiler/utils/multiprocessing.py +256 -0
  109. siliconcompiler/utils/showtools.py +10 -0
  110. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/METADATA +5 -5
  111. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/RECORD +115 -118
  112. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/entry_points.txt +3 -0
  113. siliconcompiler/schema/cmdlineschema.py +0 -250
  114. siliconcompiler/toolscripts/rhel8/install-slang.sh +0 -40
  115. siliconcompiler/toolscripts/rhel9/install-slang.sh +0 -40
  116. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +0 -47
  117. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +0 -37
  118. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +0 -37
  119. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/WHEEL +0 -0
  120. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/licenses/LICENSE +0 -0
  121. {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/top_level.txt +0 -0
siliconcompiler/design.py CHANGED
@@ -1,4 +1,3 @@
1
- import contextlib
2
1
  import re
3
2
 
4
3
  import os.path
@@ -7,29 +6,60 @@ from typing import List, Union, Tuple, Dict
7
6
 
8
7
  from siliconcompiler import utils
9
8
 
10
- from siliconcompiler import PackageSchema
9
+ from siliconcompiler import LibrarySchema
11
10
 
12
11
  from siliconcompiler.dependencyschema import DependencySchema
13
- from siliconcompiler.pathschema import PathSchema
14
12
  from siliconcompiler.schema import NamedSchema
15
13
  from siliconcompiler.schema import EditableSchema, Parameter, Scope
16
14
  from siliconcompiler.schema.utils import trim
17
15
 
18
16
 
19
17
  ###########################################################################
20
- class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
18
+ class DesignSchema(LibrarySchema, DependencySchema):
19
+ '''
20
+ Schema for a 'design', which is a chip object that can be compiled.
21
+
22
+ This class inherits from :class:`~siliconcompiler.LibrarySchema` and
23
+ :class:`~siliconcompiler.DependencySchema`, and adds parameters and methods
24
+ specific to describing a design, such as its top module, source filesets,
25
+ and compilation settings.
26
+ '''
21
27
 
22
28
  def __init__(self, name: str = None):
29
+ '''
30
+ Initializes a new DesignSchema object.
31
+
32
+ Args:
33
+ name (str, optional): The name of the design. Defaults to None.
34
+ '''
23
35
  super().__init__()
24
36
  self.set_name(name)
25
37
 
26
38
  schema_design(self)
27
39
 
28
40
  def add_dep(self, obj: NamedSchema, clobber: bool = True) -> bool:
41
+ '''
42
+ Adds a module dependency to this design.
43
+
44
+ This method extends the base `add_dep` to prevent a design from
45
+ adding a dependency on itself.
46
+
47
+ Args:
48
+ obj (NamedSchema): The dependency object to add.
49
+ clobber (bool): If True, overwrite an existing dependency with the
50
+ same name.
51
+
52
+ Returns:
53
+ bool: True if the dependency was added, False otherwise.
54
+
55
+ Raises:
56
+ TypeError: If `obj` is not a `NamedSchema`.
57
+ ValueError: If `obj` has the same name as the current design.
58
+ '''
29
59
  if not isinstance(obj, NamedSchema):
30
60
  raise TypeError(f"Cannot add an object of type: {type(obj)}")
31
61
 
32
- if obj.name() == self.name():
62
+ if obj.name == self.name:
33
63
  raise ValueError("Cannot add a dependency with the same name")
34
64
 
35
65
  return super().add_dep(obj, clobber=clobber)
@@ -42,7 +72,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
42
72
 
43
73
  Args:
44
74
  value (str): Topmodule name.
45
- fileset (str, optional): Fileset name.
75
+ fileset (str, optional): Fileset name. If not provided, the active
76
+ fileset is used.
46
77
 
47
78
  Returns:
48
79
  str: Topmodule name
@@ -63,7 +94,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
63
94
  """Returns the topmodule of a fileset.
64
95
 
65
96
  Args:
66
- fileset (str): Fileset name.
97
+ fileset (str): Fileset name. If not provided, the active fileset is
98
+ used.
67
99
 
68
100
  Returns:
69
101
  str: Topmodule name
@@ -80,9 +112,10 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
80
112
 
81
113
  Args:
82
114
  value (str or Path): Include directory name.
83
- fileset (str, optional): Fileset name.
84
- clobber (bool, optional): Clears existing list before adding item
85
- dataroot (str, optional): Data directory reference name
115
+ fileset (str, optional): Fileset name. If not provided, the active
116
+ fileset is used.
117
+ clobber (bool, optional): Clears existing list before adding item.
118
+ dataroot (str, optional): Data directory reference name.
86
119
 
87
120
  Returns:
88
121
  list[str]: List of include directories
@@ -94,7 +127,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
94
127
  """Returns include directories for a fileset.
95
128
 
96
129
  Args:
97
- fileset (str): Fileset name.
130
+ fileset (str): Fileset name. If not provided, the active fileset is
131
+ used.
98
132
 
99
133
  Returns:
100
134
  list[str]: List of include directories
@@ -110,7 +144,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
110
144
 
111
145
  Args:
112
146
  value (str or List[str]): Macro definition.
113
- fileset (str, optional): Fileset name.
147
+ fileset (str, optional): Fileset name. If not provided, the active
148
+ fileset is used.
114
149
  clobber (bool, optional): Clears existing list before adding item.
115
150
 
116
151
  Returns:
@@ -123,7 +158,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
123
158
  """Returns defined macros for a fileset.
124
159
 
125
160
  Args:
126
- fileset (str): Fileset name.
161
+ fileset (str): Fileset name. If not provided, the active fileset is
162
+ used.
127
163
 
128
164
  Returns:
129
165
  list[str]: List of macro definitions
@@ -139,8 +175,9 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
139
175
 
140
176
  Args:
141
177
  value (str or List[str]): Macro (un)definition.
142
- fileset (str, optional): Fileset name.
143
- clobber (bool, optional): CClears existing list before adding item.
178
+ fileset (str, optional): Fileset name. If not provided, the active
179
+ fileset is used.
180
+ clobber (bool, optional): Clears existing list before adding item.
144
181
 
145
182
  Returns:
146
183
  list[str]: List of macro (un)definitions
@@ -151,7 +188,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
151
188
  """Returns undefined macros for a fileset.
152
189
 
153
190
  Args:
154
- fileset (str): Fileset name.
191
+ fileset (str): Fileset name. If not provided, the active fileset is
192
+ used.
155
193
 
156
194
  Returns:
157
195
  list[str]: List of macro (un)definitions
@@ -168,10 +206,11 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
168
206
  """Adds dynamic library directories to a fileset.
169
207
 
170
208
  Args:
171
- value (str or List[str]): Library directories
172
- fileset (str, optional): Fileset name.
209
+ value (str or List[str]): Library directories.
210
+ fileset (str, optional): Fileset name. If not provided, the active
211
+ fileset is used.
173
212
  clobber (bool, optional): Clears existing list before adding item.
174
- dataroot (str, optional): Data directory reference name
213
+ dataroot (str, optional): Data directory reference name.
175
214
 
176
215
  Returns:
177
216
  list[str]: List of library directories.
@@ -183,7 +222,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
183
222
  """Returns dynamic library directories for a fileset.
184
223
 
185
224
  Args:
186
- fileset (str): Fileset name.
225
+ fileset (str): Fileset name. If not provided, the active fileset is
226
+ used.
187
227
 
188
228
  Returns:
189
229
  list[str]: List of library directories.
@@ -198,8 +238,9 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
198
238
  """Adds dynamic libraries to a fileset.
199
239
 
200
240
  Args:
201
- value (str or List[str]): Libraries
202
- fileset (str, optional): Fileset name.
241
+ value (str or List[str]): Libraries.
242
+ fileset (str, optional): Fileset name. If not provided, the active
243
+ fileset is used.
203
244
  clobber (bool, optional): Clears existing list before adding item.
204
245
 
205
246
  Returns:
@@ -211,7 +252,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
211
252
  """Returns list of dynamic libraries for a fileset.
212
253
 
213
254
  Args:
214
- fileset (str): Fileset name.
255
+ fileset (str): Fileset name. If not provided, the active fileset is
256
+ used.
215
257
 
216
258
  Returns:
217
259
  list[str]: List of libraries.
@@ -228,7 +270,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
228
270
  Args:
229
271
  name (str): Parameter name.
230
272
  value (str): Parameter value.
231
- fileset (str, optional): Fileset name.
273
+ fileset (str, optional): Fileset name. If not provided, the active
274
+ fileset is used.
232
275
 
233
276
  Returns:
234
277
  str: Parameter value
@@ -252,7 +295,8 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
252
295
 
253
296
  Args:
254
297
  name (str): Parameter name.
255
- fileset (str): Fileset name.
298
+ fileset (str): Fileset name. If not provided, the active fileset is
299
+ used.
256
300
 
257
301
  Returns:
258
302
  str: Parameter value
@@ -271,8 +315,9 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
271
315
 
272
316
  Args:
273
317
  dep (:class:`DesignSchema` or str): Dependency name or object.
274
- depfileset (str): Dependency fileset
275
- fileset (str): Fileset name.
318
+ depfileset (str): Dependency fileset.
319
+ fileset (str): Fileset name. If not provided, the active fileset is
320
+ used.
276
321
 
277
322
  """
278
323
  if fileset is None:
@@ -285,16 +330,16 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
285
330
  dep_name = dep
286
331
  dep = self.get_dep(dep_name)
287
332
  elif isinstance(dep, DesignSchema):
288
- dep_name = dep.name()
333
+ dep_name = dep.name
289
334
  self.add_dep(dep, clobber=True)
290
335
  else:
291
336
  raise TypeError("dep is not a valid type")
292
337
 
293
338
  if not isinstance(dep, DesignSchema):
294
- raise ValueError(f"cannot associate fileset ({depfileset}) with {dep.name()}")
339
+ raise ValueError(f"cannot associate fileset ({depfileset}) with {dep.name}")
295
340
 
296
- if depfileset not in dep.getkeys("fileset"):
297
- raise ValueError(f"{dep.name()} does not have {depfileset} as a fileset")
341
+ if not dep.has_fileset(depfileset):
342
+ raise ValueError(f"{dep.name} does not have {depfileset} as a fileset")
298
343
 
299
344
  return self.add("fileset", fileset, "depfileset", (dep_name, depfileset))
300
345
 
@@ -303,10 +348,11 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
303
348
  Returns list of dependency filesets.
304
349
 
305
350
  Args:
306
- fileset (str): Fileset name.
351
+ fileset (str): Fileset name. If not provided, the active fileset is
352
+ used.
307
353
 
308
354
  Returns:
309
- list[str]: List of dependencies and filesets.
355
+ list[tuple(str, str)]: List of dependencies and filesets.
310
356
  """
311
357
  if fileset is None:
312
358
  fileset = self._get_active("fileset")
@@ -316,128 +362,22 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
316
362
 
317
363
  return self.get("fileset", fileset, "depfileset")
318
364
 
319
- ###############################################
320
- def add_file(self,
321
- filename: str,
322
- fileset: str = None,
323
- filetype: str = None,
324
- clobber: bool = False,
325
- dataroot: str = None) -> List[str]:
326
- """
327
- Adds files to a fileset.
328
-
329
- .v → (source, verilog)
330
- .vhd → (source, vhdl)
331
- .sdc → (constraint, sdc)
332
- .lef → (input, lef)
333
- .def → (input, def)
334
- ... → etc.
335
-
336
- Args:
337
- filename (Path or list[Path]): File path or list of paths to add.
338
- fileset (str): Logical group to associate the file with.
339
- filetype (str, optional): Type of the file (e.g., 'verilog', 'sdc').
340
- clobber (bool, optional): Clears list before adding item
341
- dataroot (str, optional): Data directory reference name
342
-
343
- Raises:
344
- SiliconCompilerError: If fileset or filetype cannot be inferred from
345
- the file extension.
346
-
347
- Returns:
348
- list[str]: List of file paths.
349
-
350
- Notes:
351
- - This method normalizes `filename` to a string for consistency.
352
-
353
- - If no filetype is specified, filetype is inferred based on
354
- the file extension via a mapping table. (eg. .v is verilog).
355
- """
356
-
357
- if fileset is None:
358
- fileset = self._get_active("fileset")
359
-
360
- if not isinstance(fileset, str):
361
- raise ValueError("fileset key must be a string")
362
-
363
- # handle list inputs
364
- if isinstance(filename, (list, tuple)):
365
- params = []
366
- for item in filename:
367
- params.extend(
368
- self.add_file(
369
- item,
370
- fileset=fileset,
371
- clobber=clobber,
372
- filetype=filetype))
373
- return params
374
-
375
- if filename is None:
376
- raise ValueError("add_file cannot process None")
377
-
378
- # Normalize value to string in case we receive a pathlib.Path
379
- filename = str(filename)
380
-
381
- # map extension to default filetype/fileset
382
- if not filetype:
383
- ext = utils.get_file_ext(filename)
384
- iomap = utils.get_default_iomap()
385
- if ext in iomap:
386
- _, default_filetype = iomap[ext]
387
- filetype = default_filetype
388
- else:
389
- raise ValueError(f"Unrecognized file extension: {ext}")
390
-
391
- if not dataroot:
392
- dataroot = self._get_active("package")
393
-
394
- # adding files to dictionary
395
- with self.active_dataroot(dataroot):
396
- if clobber:
397
- return self.set('fileset', fileset, 'file', filetype, filename)
398
- else:
399
- return self.add('fileset', fileset, 'file', filetype, filename)
400
-
401
- ###############################################
402
- def get_file(self,
403
- fileset: str = None,
404
- filetype: str = None):
405
- """Returns a list of files from one or more filesets.
406
-
407
- Args:
408
- fileset (str or list[str]): Fileset(s) to query.
409
- filetype (str or list[str], optional): File type(s) to filter by (e.g., 'verilog').
410
-
411
- Returns:
412
- list[str]: List of file paths.
413
- """
414
-
415
- if fileset is None:
416
- fileset = self._get_active("fileset")
417
-
418
- if not isinstance(fileset, list):
419
- fileset = [fileset]
420
-
421
- if filetype and not isinstance(filetype, list):
422
- filetype = [filetype]
423
-
424
- filelist = []
425
- for fs in fileset:
426
- if not isinstance(fs, str):
427
- raise ValueError("fileset key must be a string")
428
- # handle scalar+list in argument
429
- if not filetype:
430
- filetype = self.getkeys('fileset', fs, 'file')
431
- # grab the files
432
- for ftype in filetype:
433
- filelist.extend(self.find_files('fileset', fs, 'file', ftype))
434
-
435
- return filelist
436
-
437
365
  def __write_flist(self,
438
366
  filename: str,
439
367
  filesets: List[str],
440
368
  depalias: Dict[str, Tuple[NamedSchema, str]]):
369
+ '''
370
+ Internal helper to write a Verilog-style file list (`.f` file).
371
+
372
+ This method iterates through the specified filesets (and their
373
+ dependencies), writing out `+incdir+`, `+define+`, and source file
374
+ paths.
375
+
376
+ Args:
377
+ filename (str): The path to the output file list.
378
+ filesets (List[str]): A list of fileset names to include.
379
+ depalias (Dict): A dictionary for aliasing dependencies.
380
+ '''
441
381
  written_cmd = set()
442
382
 
443
383
  with open(filename, "w") as f:
@@ -453,22 +393,35 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
453
393
 
454
394
  for lib, fileset in self.get_fileset(filesets, depalias):
455
395
  if lib.get('fileset', fileset, 'idir'):
456
- write_header(f"{lib.name()} / {fileset} / include directories")
396
+ write_header(f"{lib.name} / {fileset} / include directories")
457
397
  for idir in lib.find_files('fileset', fileset, 'idir'):
458
398
  write(f"+incdir+{idir}")
459
399
 
460
400
  if lib.get('fileset', fileset, 'define'):
461
- write_header(f"{lib.name()} / {fileset} / defines")
401
+ write_header(f"{lib.name} / {fileset} / defines")
462
402
  for define in lib.get('fileset', fileset, 'define'):
463
403
  write(f"+define+{define}")
464
404
 
465
405
  for filetype in lib.getkeys('fileset', fileset, 'file'):
466
406
  if lib.get('fileset', fileset, 'file', filetype):
467
- write_header(f"{lib.name()} / {fileset} / {filetype} files")
407
+ write_header(f"{lib.name} / {fileset} / {filetype} files")
468
408
  for file in lib.find_files('fileset', fileset, 'file', filetype):
469
409
  write(file)
470
410
 
471
411
  def __map_fileformat(self, path):
412
+ '''
413
+ Internal helper to determine file format from a file extension.
414
+
415
+ Args:
416
+ path (str): The file path.
417
+
418
+ Returns:
419
+ str: The determined file format (e.g., "flist").
420
+
421
+ Raises:
422
+ ValueError: If the file format cannot be determined from the
423
+ extension.
424
+ '''
472
425
  _, ext = os.path.splitext(path)
473
426
 
474
427
  if ext == ".f":
@@ -490,9 +443,10 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
490
443
 
491
444
  Args:
492
445
  filename (str or Path): Output file name.
493
- fileset (str or list[str]): Fileset(s) to export.
446
+ fileset (str or list[str]): Fileset(s) to export. If not provided,
447
+ the active fileset is used.
494
448
  fileformat (str, optional): Export format.
495
- depalias (dict of schema objects): Map of aliased objects
449
+ depalias (dict of schema objects): Map of aliased objects.
496
450
  """
497
451
 
498
452
  if filename is None:
@@ -518,6 +472,16 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
518
472
  raise ValueError(f"{fileformat} is not a supported filetype")
519
473
 
520
474
  def __read_flist(self, filename: str, fileset: str):
475
+ '''
476
+ Internal helper to read a Verilog-style file list (`.f` file).
477
+
478
+ This method parses the file list for `+incdir+`, `+define+`, and
479
+ source files, and populates the specified fileset in the schema.
480
+
481
+ Args:
482
+ filename (str): The path to the input file list.
483
+ fileset (str): The name of the fileset to populate.
484
+ '''
521
485
  # Extract information
522
486
  rel_path = os.path.dirname(os.path.abspath(filename))
523
487
 
@@ -549,7 +513,7 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
549
513
  all_paths = include_dirs + [os.path.dirname(f) for f in files]
550
514
  all_paths = sorted(set(all_paths))
551
515
 
552
- dataroot_root_name = f'flist-{self.name()}-{fileset}-{os.path.basename(filename)}'
516
+ dataroot_root_name = f'flist-{self.name}-{fileset}-{os.path.basename(filename)}'
553
517
  dataroots = {}
554
518
 
555
519
  for path_dir in all_paths:
@@ -597,9 +561,11 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
597
561
  Intended to support other formats in the future.
598
562
 
599
563
  Args:
600
- filename (str or Path): Output file name.
601
- fileset (str or list[str]): Filesets to import.
602
- fileformat (str, optional): Export format.
564
+ filename (str or Path): Input file name.
565
+ fileset (str or list[str]): Fileset to import into. If not
566
+ provided, the active fileset is used.
567
+ fileformat (str, optional): Import format. Inferred from file
568
+ extension if not provided.
603
569
  """
604
570
 
605
571
  if filename is None:
@@ -620,7 +586,20 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
620
586
  # Helper Functions
621
587
  ################################################
622
588
  def __set_add(self, fileset, option, value, clobber=False, typelist=None, dataroot=None):
623
- '''Sets a parameter value in schema.
589
+ '''
590
+ Internal helper to set or add a parameter value in the schema.
591
+
592
+ This function handles common tasks for setters like `add_idir` and
593
+ `add_define`, such as resolving the active fileset, checking value
594
+ types, and calling the underlying schema `set()` or `add()` methods.
595
+
596
+ Args:
597
+ fileset (str): The fileset to modify.
598
+ option (str): The parameter key to modify.
599
+ value: The value to set or add.
600
+ clobber (bool): If True, overwrite the existing value.
601
+ typelist (list): A list of allowed types for the value.
602
+ dataroot (str): The dataroot to associate with the value.
624
603
  '''
625
604
 
626
605
  if fileset is None:
@@ -654,7 +633,17 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
654
633
  return params
655
634
 
656
635
  def __get(self, fileset, option, is_file=False):
657
- '''Gets a parameter value from schema.
636
+ '''
637
+ Internal helper to get a parameter value from the schema.
638
+
639
+ This function handles common tasks for getters, such as resolving the
640
+ active fileset and optionally resolving file paths.
641
+
642
+ Args:
643
+ fileset (str): The fileset to query.
644
+ option (str): The parameter key to retrieve.
645
+ is_file (bool): If True, treat the value as a file path and
646
+ resolve it using `find_files`.
658
647
  '''
659
648
  if fileset is None:
660
649
  fileset = self._get_active("fileset")
@@ -665,44 +654,34 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
665
654
  return self.find_files('fileset', fileset, option)
666
655
  return self.get('fileset', fileset, option)
667
656
 
668
- @contextlib.contextmanager
669
- def active_fileset(self, fileset: str):
657
+ @classmethod
658
+ def _getdict_type(cls) -> str:
670
659
  """
671
- Use this context to temporarily set a design fileset.
660
+ Returns the meta data for getdict.
672
661
 
673
- Raises:
674
- TypeError: if fileset is not a string
675
- ValueError: if fileset if an empty string
676
-
677
- Args:
678
- fileset (str): name of the fileset
679
-
680
- Example:
681
- >>> with design.active_fileset("rtl"):
682
- ... design.set_topmodule("top")
683
- Sets the top module for the rtl fileset as top.
662
+ This is used to identify the object type during serialization.
684
663
  """
685
- if not isinstance(fileset, str):
686
- raise TypeError("fileset must a string")
687
- if not fileset:
688
- raise ValueError("fileset cannot be an empty string")
689
664
 
690
- with self._active(fileset=fileset):
691
- yield
665
+ return DesignSchema.__name__
692
666
 
693
667
  def get_fileset(self,
694
668
  filesets: Union[List[str], str],
695
669
  alias: Dict[str, Tuple[NamedSchema, str]] = None) -> \
696
670
  List[Tuple[NamedSchema, str]]:
697
671
  """
698
- Computes the filesets this object required for a given set of filesets
672
+ Computes the full, recursive list of (dependency, fileset) tuples
673
+ required for a given set of top-level filesets.
674
+
675
+ This method traverses the design's dependency graph.
699
676
 
700
677
  Args:
701
- filesets (list of str): List of filesets to evaluate
702
- alias (dict of schema objects): Map of aliased objects
678
+ filesets (list of str): List of top-level filesets to evaluate.
679
+ alias (dict of schema objects): Map of aliased objects to
680
+ substitute during traversal.
703
681
 
704
682
  Returns:
705
- List of tuples (dependency object, fileset)
683
+ List[Tuple[NamedSchema, str]]: A flattened, unique list of
684
+ (dependency, fileset) tuples.
706
685
  """
707
686
  if alias is None:
708
687
  alias = {}
@@ -713,8 +692,7 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
713
692
 
714
693
  mapping = []
715
694
  for fileset in filesets:
716
- if not self.valid("fileset", fileset):
717
- raise ValueError(f"{fileset} is not defined in {self.name()}")
695
+ self._assert_fileset(fileset)
718
696
 
719
697
  mapping.append((self, fileset))
720
698
  for dep, depfileset in self.get("fileset", fileset, "depfileset"):
@@ -744,29 +722,20 @@ class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
744
722
  # Schema
745
723
  ###########################################################################
746
724
  def schema_design(schema):
725
+ '''
726
+ Defines the schema parameters specific to a design.
747
727
 
748
- schema = EditableSchema(schema)
728
+ This function is called by the `DesignSchema` constructor to set up
729
+ its unique schema elements, such as `topmodule`, `idir`, `define`, etc.,
730
+ under the `fileset` key.
749
731
 
750
- ###########################
751
- # Files
752
- ###########################
732
+ Args:
733
+ schema (DesignSchema): The schema object to configure.
734
+ '''
735
+
736
+ schema = EditableSchema(schema)
753
737
 
754
738
  fileset = 'default'
755
- filetype = 'default'
756
- schema.insert(
757
- 'fileset', fileset, 'file', filetype,
758
- Parameter(
759
- ['file'],
760
- scope=Scope.GLOBAL,
761
- shorthelp="Design files",
762
- example=[
763
- "api: chip.set('fileset', 'rtl', 'file', 'verilog', 'mytop.v')",
764
- "api: chip.set('fileset', 'testbench', 'file', 'verilog', 'tb.v')"],
765
- help=trim("""
766
- List of files grouped as a named set ('fileset'). The exact names of
767
- filetypes and filesets must match the names used in tasks
768
- called during flowgraph execution. The files are processed in
769
- the order specified by the ordered file list.""")))
770
739
 
771
740
  ###########################
772
741
  # Options