siliconcompiler 0.35.1__py3-none-any.whl → 0.35.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 (57) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_install.py +1 -1
  3. siliconcompiler/apps/sc_issue.py +8 -16
  4. siliconcompiler/apps/smake.py +106 -100
  5. siliconcompiler/checklist.py +349 -91
  6. siliconcompiler/design.py +8 -1
  7. siliconcompiler/flowgraph.py +419 -130
  8. siliconcompiler/flows/showflow.py +1 -2
  9. siliconcompiler/library.py +6 -5
  10. siliconcompiler/package/https.py +10 -5
  11. siliconcompiler/project.py +87 -37
  12. siliconcompiler/remote/client.py +17 -6
  13. siliconcompiler/scheduler/scheduler.py +284 -59
  14. siliconcompiler/scheduler/schedulernode.py +154 -102
  15. siliconcompiler/schema/__init__.py +3 -2
  16. siliconcompiler/schema/_metadata.py +1 -1
  17. siliconcompiler/schema/baseschema.py +210 -93
  18. siliconcompiler/schema/namedschema.py +21 -13
  19. siliconcompiler/schema/parameter.py +8 -1
  20. siliconcompiler/schema/safeschema.py +18 -7
  21. siliconcompiler/schema_support/dependencyschema.py +23 -3
  22. siliconcompiler/schema_support/filesetschema.py +10 -4
  23. siliconcompiler/schema_support/option.py +37 -34
  24. siliconcompiler/schema_support/pathschema.py +7 -2
  25. siliconcompiler/schema_support/record.py +5 -4
  26. siliconcompiler/targets/asap7_demo.py +4 -1
  27. siliconcompiler/tool.py +100 -8
  28. siliconcompiler/tools/__init__.py +10 -7
  29. siliconcompiler/tools/bambu/convert.py +19 -0
  30. siliconcompiler/tools/builtin/__init__.py +3 -2
  31. siliconcompiler/tools/builtin/filter.py +108 -0
  32. siliconcompiler/tools/builtin/importfiles.py +154 -0
  33. siliconcompiler/tools/execute/exec_input.py +4 -3
  34. siliconcompiler/tools/gtkwave/show.py +6 -2
  35. siliconcompiler/tools/icarus/compile.py +1 -0
  36. siliconcompiler/tools/klayout/scripts/klayout_show.py +1 -1
  37. siliconcompiler/tools/klayout/show.py +17 -5
  38. siliconcompiler/tools/openroad/screenshot.py +0 -1
  39. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
  40. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +2 -0
  41. siliconcompiler/tools/openroad/show.py +10 -0
  42. siliconcompiler/tools/surfer/show.py +7 -2
  43. siliconcompiler/tools/verilator/compile.py +2 -2
  44. siliconcompiler/tools/yosys/prepareLib.py +7 -2
  45. siliconcompiler/tools/yosys/syn_asic.py +20 -2
  46. siliconcompiler/toolscripts/_tools.json +5 -5
  47. siliconcompiler/toolscripts/rhel9/{install-yosys-wildebeest.sh → install-wildebeest.sh} +5 -5
  48. siliconcompiler/toolscripts/ubuntu22/{install-yosys-wildebeest.sh → install-wildebeest.sh} +5 -5
  49. siliconcompiler/toolscripts/ubuntu24/{install-yosys-wildebeest.sh → install-wildebeest.sh} +5 -5
  50. siliconcompiler/utils/__init__.py +1 -2
  51. siliconcompiler/utils/issue.py +38 -45
  52. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/METADATA +4 -4
  53. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/RECORD +57 -55
  54. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/WHEEL +0 -0
  55. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/entry_points.txt +0 -0
  56. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/licenses/LICENSE +0 -0
  57. {siliconcompiler-0.35.1.dist-info → siliconcompiler-0.35.3.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,5 @@
1
1
  from siliconcompiler import Flowgraph
2
2
  from siliconcompiler import ShowTask
3
- from siliconcompiler.tools import get_task
4
3
 
5
4
 
6
5
  class ShowFlow(Flowgraph):
@@ -31,5 +30,5 @@ class ShowFlow(Flowgraph):
31
30
  ##################################################
32
31
  if __name__ == "__main__":
33
32
  from siliconcompiler import ShowTask
34
- flow = ShowFlow(get_task(ShowTask, "gds"))
33
+ flow = ShowFlow(ShowTask.get_task("gds"))
35
34
  flow.write_flowgraph(f"{flow.name}.png")
@@ -7,7 +7,7 @@ from siliconcompiler.schema_support.filesetschema import FileSetSchema
7
7
  from siliconcompiler.schema_support.pathschema import PathSchema
8
8
  from siliconcompiler.schema import NamedSchema, BaseSchema
9
9
 
10
- from siliconcompiler.schema import EditableSchema, Parameter, Scope, PerNode
10
+ from siliconcompiler.schema import EditableSchema, Parameter, Scope, PerNode, LazyLoad
11
11
  from siliconcompiler.schema.utils import trim
12
12
 
13
13
 
@@ -99,7 +99,8 @@ class ToolLibrarySchema(LibrarySchema):
99
99
 
100
100
  def _from_dict(self, manifest: Dict,
101
101
  keypath: Union[List[str], Tuple[str, ...]],
102
- version: Optional[Tuple[int, ...]] = None) \
102
+ version: Optional[Tuple[int, ...]] = None,
103
+ lazyload: LazyLoad = LazyLoad.ON) \
103
104
  -> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
104
105
  """
105
106
  Constructs a schema from a dictionary.
@@ -112,7 +113,7 @@ class ToolLibrarySchema(LibrarySchema):
112
113
  Returns:
113
114
  dict: The constructed dictionary.
114
115
  """
115
- if "tool" in manifest:
116
+ if not lazyload.is_enforced and "tool" in manifest:
116
117
  # collect tool keys
117
118
  tool_keys = self.allkeys("tool")
118
119
 
@@ -136,7 +137,7 @@ class ToolLibrarySchema(LibrarySchema):
136
137
  if not manifest["tool"]:
137
138
  del manifest["tool"]
138
139
 
139
- return super()._from_dict(manifest, keypath, version)
140
+ return super()._from_dict(manifest, keypath, version=version, lazyload=lazyload)
140
141
 
141
142
  def _generate_doc(self, doc,
142
143
  ref_root: str = "",
@@ -196,7 +197,7 @@ class ToolLibrarySchema(LibrarySchema):
196
197
  return None
197
198
 
198
199
 
199
- class StdCellLibrary(ToolLibrarySchema, DependencySchema):
200
+ class StdCellLibrary(DependencySchema, ToolLibrarySchema):
200
201
  """
201
202
  A class for managing standard cell library schemas.
202
203
  """
@@ -114,11 +114,16 @@ class HTTPResolver(RemoteResolver):
114
114
  except tarfile.ReadError:
115
115
  fileobj.seek(0)
116
116
  try:
117
- with zipfile.ZipFile(fileobj) as zip_ref:
118
- zip_ref.extractall(path=self.cache_path)
119
- except zipfile.BadZipFile:
120
- raise TypeError(f"Could not extract file from {data_url}. "
121
- "File is not a valid tar.gz or zip archive.")
117
+ with tarfile.open(fileobj=fileobj, mode='r:bz2') as tar_ref:
118
+ tar_ref.extractall(path=self.cache_path)
119
+ except tarfile.ReadError:
120
+ fileobj.seek(0)
121
+ try:
122
+ with zipfile.ZipFile(fileobj) as zip_ref:
123
+ zip_ref.extractall(path=self.cache_path)
124
+ except zipfile.BadZipFile:
125
+ raise TypeError(f"Could not extract file from {data_url}. "
126
+ "File is not a valid tar.gz or zip archive.")
122
127
 
123
128
  # --- GitHub-specific directory flattening ---
124
129
  # GitHub archives often have a single top-level directory like 'repo-v1.0'.
@@ -5,10 +5,11 @@ import uuid
5
5
 
6
6
  import os.path
7
7
 
8
- from typing import Union, List, Tuple, TextIO
8
+ from typing import Union, List, Tuple, TextIO, Optional, Dict, Set
9
9
 
10
10
  from siliconcompiler.schema import BaseSchema, NamedSchema, EditableSchema, Parameter, Scope, \
11
- __version__ as schema_version
11
+ __version__ as schema_version, \
12
+ LazyLoad
12
13
 
13
14
  from siliconcompiler import Design
14
15
  from siliconcompiler import Flowgraph
@@ -32,7 +33,6 @@ from siliconcompiler.utils import get_file_ext
32
33
  from siliconcompiler.utils.multiprocessing import MPManager
33
34
  from siliconcompiler.utils.paths import jobdir, workdir
34
35
  from siliconcompiler.flows.showflow import ShowFlow
35
- from siliconcompiler.tools import get_task
36
36
 
37
37
 
38
38
  class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
@@ -43,7 +43,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
43
43
  and reporting.
44
44
  """
45
45
 
46
- def __init__(self, design: Union[Design, str] = None):
46
+ def __init__(self, design: Optional[Union[Design, str]] = None):
47
47
  """
48
48
  Initializes a new Project instance.
49
49
 
@@ -108,7 +108,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
108
108
  is not intended for external use."""))
109
109
 
110
110
  schema.insert("checklist", "default", Checklist())
111
- schema.insert("library", BaseSchema())
111
+ schema.insert("library", _ProjectLibrary())
112
112
  schema.insert("flowgraph", "default", Flowgraph())
113
113
  schema.insert("metric", MetricSchema())
114
114
  schema.insert("record", RecordSchema())
@@ -290,26 +290,11 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
290
290
  """
291
291
  return Project.__name__
292
292
 
293
- def __populate_deps(self, obj: DependencySchema = None):
294
- """
295
- Ensures that all loaded dependencies (like libraries) within the project
296
- contain correct internal pointers back to the project's libraries.
297
- This is crucial for maintaining a consistent and navigable schema graph.
298
-
299
- Args:
300
- obj (DependencySchema, optional): An optional dependency object to
301
- reset and populate. If None, all existing library dependencies
302
- in the project are processed. Defaults to None.
303
- """
304
- if obj:
305
- obj._reset_deps()
306
- dep_map = {name: self.get("library", name, field="schema")
307
- for name in self.getkeys("library")}
308
- for obj in dep_map.values():
309
- if isinstance(obj, DependencySchema):
310
- obj._populate_deps(dep_map)
311
-
312
- def _from_dict(self, manifest, keypath, version=None):
293
+ def _from_dict(self, manifest: Dict,
294
+ keypath: Union[List[str], Tuple[str, ...]],
295
+ version: Optional[Tuple[int, ...]] = None,
296
+ lazyload: LazyLoad = LazyLoad.ON) \
297
+ -> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
313
298
  """
314
299
  Populates the project's schema from a dictionary representation.
315
300
 
@@ -326,15 +311,13 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
326
311
  Returns:
327
312
  Any: The result of the superclass's `_from_dict` method.
328
313
  """
329
- ret = super()._from_dict(manifest, keypath, version)
330
-
331
- # Restore dependencies
332
- self.__populate_deps()
314
+ ret = super()._from_dict(manifest, keypath, version=version, lazyload=lazyload)
333
315
 
334
- # Preserve logger in history
335
- for history in self.getkeys("history"):
336
- hist = self.get("history", history, field="schema")
337
- hist.__logger = self.__logger
316
+ if not lazyload.is_enforced:
317
+ # Preserve logger in history
318
+ for history in self.getkeys("history"):
319
+ hist: "Project" = self.get("history", history, field="schema")
320
+ hist.__logger = self.__logger
338
321
 
339
322
  return ret
340
323
 
@@ -393,7 +376,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
393
376
  self.add_dep(dep)
394
377
 
395
378
  # Rebuild dependencies to ensure instances are correct
396
- self.__populate_deps(obj)
379
+ self.get("library", field="schema")._populate_deps(obj)
397
380
 
398
381
  def __import_flow(self, flow: Flowgraph):
399
382
  """
@@ -665,6 +648,9 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
665
648
  # Pass along manager address
666
649
  state["__manager__"] = MPManager._get_manager_address()
667
650
 
651
+ # Pass along logger level
652
+ state["__loglevel__"] = self.logger.level
653
+
668
654
  return state
669
655
 
670
656
  def __setstate__(self, state):
@@ -677,6 +663,10 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
677
663
  Args:
678
664
  state (dict): The deserialized state of the object.
679
665
  """
666
+ # Retrieve log level
667
+ loglevel = state["__loglevel__"]
668
+ del state["__loglevel__"]
669
+
680
670
  # Retrieve manager address
681
671
  MPManager._set_manager_address(state["__manager__"])
682
672
  del state["__manager__"]
@@ -685,6 +675,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
685
675
 
686
676
  # Reinitialize logger on restore
687
677
  self.__init_logger()
678
+ self.logger.setLevel(loglevel)
688
679
 
689
680
  # Restore callbacks
690
681
  self.__init_option_callbacks()
@@ -1155,7 +1146,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
1155
1146
  '''
1156
1147
  tool_cls = ScreenshotTask if screenshot else ShowTask
1157
1148
 
1158
- sc_jobname = self.get("option", "jobname")
1149
+ sc_jobname = self.option.get_jobname()
1159
1150
  sc_step, sc_index = None, None
1160
1151
 
1161
1152
  has_filename = filename is not None
@@ -1220,12 +1211,13 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
1220
1211
  return None
1221
1212
 
1222
1213
  # Create copy of project to avoid changing user project
1223
- proj = self.copy()
1214
+ proj: Project = self.copy()
1224
1215
  proj.set_flow(ShowFlow(task))
1225
1216
 
1226
1217
  # Setup options:
1227
1218
  for option, value in [
1228
1219
  ("track", False),
1220
+ ("remote", False),
1229
1221
  ("hash", False),
1230
1222
  ("nodisplay", False),
1231
1223
  ("continue", True),
@@ -1242,7 +1234,7 @@ class Project(PathSchemaBase, CommandLineSchema, BaseSchema):
1242
1234
  proj.set("option", "jobname", jobname)
1243
1235
 
1244
1236
  # Setup in task variables
1245
- task: ShowTask = get_task(proj, filter=task.__class__)
1237
+ task: ShowTask = task.find_task(proj)
1246
1238
  task.set_showfilepath(filename)
1247
1239
  task.set_showfiletype(filetype)
1248
1240
  task.set_shownode(jobname=sc_jobname, step=sc_step, index=sc_index)
@@ -1277,3 +1269,61 @@ class Lint(Project):
1277
1269
  @classmethod
1278
1270
  def _getdict_type(cls) -> str:
1279
1271
  return Lint.__name__
1272
+
1273
+
1274
+ class _ProjectLibrary(BaseSchema):
1275
+ def _from_dict(self, manifest: Dict,
1276
+ keypath: Union[List[str], Tuple[str, ...]],
1277
+ version: Optional[Tuple[int, ...]] = None,
1278
+ lazyload: LazyLoad = LazyLoad.ON) \
1279
+ -> Tuple[Set[Tuple[str, ...]], Set[Tuple[str, ...]]]:
1280
+ """
1281
+ Populates the project's schema from a dictionary representation.
1282
+
1283
+ This method is typically used during deserialization or when loading
1284
+ a project state from a manifest. After loading the data, it ensures
1285
+ that internal dependencies are correctly re-established.
1286
+
1287
+ Args:
1288
+ manifest (dict): The dictionary containing the schema data.
1289
+ keypath (list): The current keypath being processed (used internally
1290
+ for recursive loading).
1291
+ version (str, optional): The schema version of the manifest. Defaults to None.
1292
+
1293
+ Returns:
1294
+ Any: The result of the superclass's `_from_dict` method.
1295
+ """
1296
+ ret = super()._from_dict(manifest, keypath, version=version, lazyload=lazyload)
1297
+
1298
+ if not lazyload.is_enforced:
1299
+ # Restore dependencies
1300
+ self._populate_deps(complete=True)
1301
+
1302
+ return ret
1303
+
1304
+ def _populate_deps(self, obj: Optional[DependencySchema] = None, complete: bool = False):
1305
+ """
1306
+ Ensures that all loaded dependencies (like libraries) within the project
1307
+ contain correct internal pointers back to the project's libraries.
1308
+ This is crucial for maintaining a consistent and navigable schema graph.
1309
+
1310
+ Args:
1311
+ obj (DependencySchema, optional): An optional dependency object to
1312
+ reset and populate. If None, all existing library dependencies
1313
+ in the project are processed. Defaults to None.
1314
+ complete (bool, optional): If True, performs a full reset of all
1315
+ DependencySchema objects before populating dependencies. This
1316
+ ensures a clean state during manifest deserialization. Defaults to False.
1317
+ """
1318
+ if obj:
1319
+ obj._reset_deps()
1320
+ dep_map = {name: self.get(name, field="schema") for name in self.getkeys()}
1321
+
1322
+ if complete:
1323
+ for obj in dep_map.values():
1324
+ if isinstance(obj, DependencySchema):
1325
+ obj._reset_deps()
1326
+
1327
+ for obj in dep_map.values():
1328
+ if isinstance(obj, DependencySchema):
1329
+ obj._populate_deps(dep_map)
@@ -18,7 +18,8 @@ from siliconcompiler import NodeStatus as SCNodeStatus
18
18
  from siliconcompiler._metadata import default_server
19
19
  from siliconcompiler.flowgraph import RuntimeFlowgraph
20
20
  from siliconcompiler.scheduler import Scheduler
21
- from siliconcompiler.schema import Journal
21
+ from siliconcompiler.schema import Journal, Parameter
22
+ from siliconcompiler.package import PythonPathResolver, FileResolver, KeyPathResolver
22
23
 
23
24
  from siliconcompiler.utils.logging import get_console_formatter
24
25
  from siliconcompiler.utils.curation import collect
@@ -573,19 +574,29 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
573
574
 
574
575
  # Ensure dataroots with python sources are copied
575
576
  for key in self.__project.allkeys():
576
- key_type = self.__project.get(*key, field='type')
577
+ if key[0] == "history":
578
+ continue
579
+
580
+ param: Parameter = self.__project.get(*key, field=None)
581
+ key_type: str = param.get(field="type")
577
582
 
578
583
  if 'dir' in key_type or 'file' in key_type:
579
- for _, step, index in self.__project.get(*key, field=None).getvalues(
580
- return_defvalue=False):
581
- dataroots = self.__project.get(*key, field='dataroot', step=step, index=index)
584
+ schema_obj = self.__project.get(*key[:-1], field="schema")
585
+ dataroot_objs = schema_obj._find_files_dataroot_resolvers(True)
586
+
587
+ for value, step, index in param.getvalues():
588
+ if not value:
589
+ continue
590
+ dataroots = param.get(field='dataroot', step=step, index=index)
582
591
  if not isinstance(dataroots, list):
583
592
  dataroots = [dataroots]
584
593
  force_copy = False
585
594
  for dataroot in dataroots:
586
595
  if not dataroot:
587
596
  continue
588
- if dataroot.startswith('python://'):
597
+ dataroot_resolver = dataroot_objs.get(dataroot, None)
598
+ if isinstance(dataroot_resolver,
599
+ (PythonPathResolver, FileResolver, KeyPathResolver)):
589
600
  force_copy = True
590
601
  if force_copy:
591
602
  self.__project.set(*key, True, field='copy', step=step, index=index)