siliconcompiler 0.35.4__py3-none-any.whl → 0.36.1__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 (89) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/constraints/__init__.py +4 -1
  3. siliconcompiler/constraints/asic_timing.py +230 -38
  4. siliconcompiler/constraints/fpga_timing.py +209 -14
  5. siliconcompiler/constraints/timing_mode.py +82 -0
  6. siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
  7. siliconcompiler/flowgraph.py +95 -42
  8. siliconcompiler/flows/generate_openroad_rcx.py +2 -2
  9. siliconcompiler/flows/highresscreenshotflow.py +37 -0
  10. siliconcompiler/library.py +2 -1
  11. siliconcompiler/package/__init__.py +39 -45
  12. siliconcompiler/project.py +4 -1
  13. siliconcompiler/scheduler/scheduler.py +64 -35
  14. siliconcompiler/scheduler/schedulernode.py +5 -2
  15. siliconcompiler/scheduler/slurm.py +7 -6
  16. siliconcompiler/scheduler/taskscheduler.py +19 -16
  17. siliconcompiler/schema/_metadata.py +1 -1
  18. siliconcompiler/schema/namedschema.py +2 -4
  19. siliconcompiler/schema_support/cmdlineschema.py +0 -3
  20. siliconcompiler/schema_support/dependencyschema.py +0 -6
  21. siliconcompiler/schema_support/record.py +4 -3
  22. siliconcompiler/tool.py +58 -27
  23. siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
  24. siliconcompiler/tools/chisel/convert.py +44 -0
  25. siliconcompiler/tools/ghdl/convert.py +37 -2
  26. siliconcompiler/tools/icarus/compile.py +14 -0
  27. siliconcompiler/tools/keplerformal/__init__.py +7 -0
  28. siliconcompiler/tools/keplerformal/lec.py +112 -0
  29. siliconcompiler/tools/klayout/drc.py +14 -0
  30. siliconcompiler/tools/klayout/export.py +40 -0
  31. siliconcompiler/tools/klayout/operations.py +40 -0
  32. siliconcompiler/tools/klayout/screenshot.py +66 -1
  33. siliconcompiler/tools/klayout/scripts/klayout_export.py +10 -40
  34. siliconcompiler/tools/klayout/scripts/klayout_show.py +4 -4
  35. siliconcompiler/tools/klayout/scripts/klayout_utils.py +13 -1
  36. siliconcompiler/tools/montage/tile.py +26 -12
  37. siliconcompiler/tools/openroad/__init__.py +11 -0
  38. siliconcompiler/tools/openroad/_apr.py +780 -11
  39. siliconcompiler/tools/openroad/antenna_repair.py +26 -0
  40. siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -0
  41. siliconcompiler/tools/openroad/global_placement.py +67 -0
  42. siliconcompiler/tools/openroad/global_route.py +15 -0
  43. siliconcompiler/tools/openroad/init_floorplan.py +19 -2
  44. siliconcompiler/tools/openroad/macro_placement.py +252 -0
  45. siliconcompiler/tools/openroad/power_grid.py +43 -0
  46. siliconcompiler/tools/openroad/power_grid_analysis.py +1 -1
  47. siliconcompiler/tools/openroad/rcx_bench.py +28 -0
  48. siliconcompiler/tools/openroad/rcx_extract.py +14 -0
  49. siliconcompiler/tools/openroad/rdlroute.py +14 -0
  50. siliconcompiler/tools/openroad/repair_design.py +41 -0
  51. siliconcompiler/tools/openroad/repair_timing.py +54 -0
  52. siliconcompiler/tools/openroad/screenshot.py +31 -1
  53. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +8 -0
  54. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +54 -15
  55. siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +6 -4
  56. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +4 -4
  57. siliconcompiler/tools/openroad/scripts/common/procs.tcl +14 -5
  58. siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
  59. siliconcompiler/tools/openroad/scripts/common/reports.tcl +6 -3
  60. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
  61. siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
  62. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
  63. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
  64. siliconcompiler/tools/openroad/write_data.py +78 -2
  65. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
  66. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
  67. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +12 -14
  68. siliconcompiler/tools/opensta/timing.py +42 -3
  69. siliconcompiler/tools/slang/elaborate.py +16 -1
  70. siliconcompiler/tools/surelog/parse.py +54 -0
  71. siliconcompiler/tools/verilator/compile.py +120 -0
  72. siliconcompiler/tools/vivado/syn_fpga.py +27 -0
  73. siliconcompiler/tools/vpr/route.py +40 -0
  74. siliconcompiler/tools/xdm/convert.py +14 -0
  75. siliconcompiler/tools/xyce/simulate.py +26 -0
  76. siliconcompiler/tools/yosys/lec_asic.py +13 -0
  77. siliconcompiler/tools/yosys/syn_asic.py +332 -3
  78. siliconcompiler/tools/yosys/syn_fpga.py +32 -0
  79. siliconcompiler/toolscripts/_tools.json +9 -4
  80. siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
  81. siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
  82. siliconcompiler/utils/multiprocessing.py +11 -0
  83. siliconcompiler/utils/settings.py +70 -49
  84. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/METADATA +4 -4
  85. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/RECORD +89 -83
  86. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/WHEEL +0 -0
  87. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/entry_points.txt +0 -0
  88. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/licenses/LICENSE +0 -0
  89. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import os
3
3
  import logging
4
+ import threading
4
5
 
5
6
  import os.path
6
7
 
@@ -24,9 +25,14 @@ class SettingsManager:
24
25
 
25
26
  Args:
26
27
  filepath (str): The path to the JSON file where settings are stored.
28
+ If None, settings are kept in memory only.
29
+ logger (logging.Logger): Logger for logging errors and information.
30
+ timeout (float): Timeout in seconds for acquiring the file lock.
27
31
  """
28
32
  self.__filepath = filepath
29
- self.__lock = InterProcessLock(self.__filepath + ".lock")
33
+ if self.__filepath is not None:
34
+ self.__lock = InterProcessLock(self.__filepath + ".lock")
35
+ self.__settings_lock = threading.Lock()
30
36
  self.__timeout = timeout
31
37
  self.__logger = logger.getChild("settings")
32
38
  self.__settings = {}
@@ -37,58 +43,63 @@ class SettingsManager:
37
43
  Internal method to load settings from disk.
38
44
  It handles missing files and malformed JSON gracefully.
39
45
  """
40
- if not os.path.exists(self.__filepath):
46
+ if self.__filepath is None or not os.path.exists(self.__filepath):
41
47
  self.__settings = {}
42
48
  return
43
49
 
44
- try:
45
- if self.__lock.acquire(timeout=self.__timeout):
46
- try:
47
- with sc_open(self.__filepath, encoding='utf-8') as f:
48
- data = json.load(f)
49
- finally:
50
- self.__lock.release()
51
- else:
52
- self.__logger.error(f"Timeout acquiring lock for {self.__filepath}. "
50
+ with self.__settings_lock:
51
+ try:
52
+ if self.__lock.acquire(timeout=self.__timeout):
53
+ try:
54
+ with sc_open(self.__filepath, encoding='utf-8') as f:
55
+ data = json.load(f)
56
+ finally:
57
+ self.__lock.release()
58
+ else:
59
+ self.__logger.error(f"Timeout acquiring lock for {self.__filepath}. "
60
+ "Starting with empty settings.")
61
+ data = {}
62
+
63
+ # Ensure the loaded data is actually a dictionary
64
+ if isinstance(data, dict):
65
+ self.__settings = data
66
+ else:
67
+ # If valid JSON but not a dict (e.g. a list), reset to empty
68
+ self.__logger.warning(f"File {self.__filepath} did not contain a JSON object. "
69
+ "Resetting.")
70
+ self.__settings = {}
71
+
72
+ except json.JSONDecodeError:
73
+ self.__logger.error(f"File {self.__filepath} is malformed. "
53
74
  "Starting with empty settings.")
54
- data = {}
55
-
56
- # Ensure the loaded data is actually a dictionary
57
- if isinstance(data, dict):
58
- self.__settings = data
59
- else:
60
- # If valid JSON but not a dict (e.g. a list), reset to empty
61
- self.__logger.warning(f"File {self.__filepath} did not contain a JSON object. "
62
- "Resetting.")
63
75
  self.__settings = {}
64
-
65
- except json.JSONDecodeError:
66
- self.__logger.error(f"File {self.__filepath} is malformed. "
67
- "Starting with empty settings.")
68
- self.__settings = {}
69
- except Exception as e:
70
- # Catch-all for permission errors, etc., to ensure __init__ doesn't crash
71
- self.__logger.error(f"Unexpected error loading settings: {e}")
72
- self.__settings = {}
76
+ except Exception as e:
77
+ # Catch-all for permission errors, etc., to ensure __init__ doesn't crash
78
+ self.__logger.error(f"Unexpected error loading settings: {e}")
79
+ self.__settings = {}
73
80
 
74
81
  def save(self):
75
82
  """
76
83
  Save the current settings to the disk in JSON format.
77
84
  """
85
+ if self.__filepath is None:
86
+ return
87
+
78
88
  try:
79
89
  # Ensure directory exists
80
90
  directory = os.path.dirname(self.__filepath)
81
91
  if directory and not os.path.exists(directory):
82
92
  os.makedirs(directory)
83
93
 
84
- with self.__lock:
85
- with open(self.__filepath, 'w', encoding='utf-8') as f:
86
- json.dump(self.__settings, f, indent=4)
94
+ with self.__settings_lock:
95
+ with self.__lock:
96
+ with open(self.__filepath, 'w', encoding='utf-8') as f:
97
+ json.dump(self.__settings, f, indent=4)
87
98
  except Exception as e:
88
99
  self.__logger.error(f"Failed to save settings to {self.__filepath}: {e}")
89
100
  raise e
90
101
 
91
- def set(self, category: str, key: str, value):
102
+ def set(self, category: str, key: str, value, keep: bool = False):
92
103
  """
93
104
  Set a specific setting within a category.
94
105
 
@@ -96,11 +107,15 @@ class SettingsManager:
96
107
  category (str): The group name (e.g., 'showtools', 'options').
97
108
  key (str): The specific setting name.
98
109
  value: The value to store (must be JSON serializable).
110
+ keep (bool): If True, do not overwrite existing value.
99
111
  """
100
- if category not in self.__settings:
101
- self.__settings[category] = {}
112
+ with self.__settings_lock:
113
+ if category not in self.__settings:
114
+ self.__settings[category] = {}
102
115
 
103
- self.__settings[category][key] = value
116
+ if keep and key in self.__settings[category]:
117
+ return
118
+ self.__settings[category][key] = value
104
119
 
105
120
  def get(self, category: str, key: str, default=None):
106
121
  """
@@ -114,28 +129,34 @@ class SettingsManager:
114
129
  Returns:
115
130
  The stored value or the default.
116
131
  """
117
- if category not in self.__settings:
118
- return default
132
+ with self.__settings_lock:
133
+ if category not in self.__settings:
134
+ return default
119
135
 
120
- return self.__settings[category].get(key, default)
136
+ return self.__settings[category].get(key, default)
121
137
 
122
138
  def get_category(self, category: str):
123
139
  """
124
140
  Retrieve all settings for a specific category.
125
141
  Returns an empty dict if category does not exist.
126
142
  """
127
- return self.__settings.get(category, {})
143
+ with self.__settings_lock:
144
+ if category not in self.__settings:
145
+ self.__settings[category] = {}
146
+
147
+ return self.__settings.get(category).copy()
128
148
 
129
149
  def delete(self, category: str, key: Optional[str] = None):
130
150
  """
131
151
  Remove a setting.
132
152
  """
133
- if category in self.__settings:
134
- if key:
135
- if key in self.__settings[category]:
136
- del self.__settings[category][key]
137
- # Clean up empty categories
138
- if not self.__settings[category]:
139
- del self.__settings[category]
140
- else:
141
- del self.__settings[category]
153
+ with self.__settings_lock:
154
+ if category in self.__settings:
155
+ if key:
156
+ if key in self.__settings[category]:
157
+ del self.__settings[category][key]
158
+ # Clean up empty categories
159
+ if not self.__settings[category]:
160
+ del self.__settings[category]
161
+ else:
162
+ del self.__settings[category]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siliconcompiler
3
- Version: 0.35.4
3
+ Version: 0.36.1
4
4
  Summary: A compiler framework that automates translation from source code to silicon.
5
5
  Author: Zero ASIC
6
6
  License: Apache License 2.0
@@ -31,14 +31,14 @@ Requires-Dist: docker<8.0.0,>=7.1.0
31
31
  Requires-Dist: fastjsonschema<2.22.0,>=2.20.0
32
32
  Requires-Dist: graphviz<0.22,>=0.20
33
33
  Requires-Dist: orjson<4,>=3.11.0
34
- Requires-Dist: packaging<25,>=21.3
34
+ Requires-Dist: packaging<26,>=21.3
35
35
  Requires-Dist: requests<2.33.0,>=2.32.0
36
36
  Requires-Dist: Pillow<11.4.0,>=11.3.0
37
37
  Requires-Dist: PyYAML<7.0.0,>=6.0.0
38
38
  Requires-Dist: GitPython<3.2,>=3.1.44
39
39
  Requires-Dist: PyGithub<2.9.0,>=2.8.0
40
40
  Requires-Dist: urllib3>=1.26.0
41
- Requires-Dist: lambdapdk>=0.2.4
41
+ Requires-Dist: lambdapdk>=0.2.6
42
42
  Requires-Dist: fasteners>=0.20
43
43
  Requires-Dist: pandas>=1.1.5
44
44
  Requires-Dist: psutil>=5.8.0
@@ -61,7 +61,7 @@ Requires-Dist: responses==0.25.8; extra == "test"
61
61
  Requires-Dist: PyVirtualDisplay==3.0; extra == "test"
62
62
  Provides-Extra: lint
63
63
  Requires-Dist: flake8==7.3.0; extra == "lint"
64
- Requires-Dist: tclint==0.6.2; extra == "lint"
64
+ Requires-Dist: tclint==0.7.0; extra == "lint"
65
65
  Requires-Dist: codespell==2.4.1; extra == "lint"
66
66
  Provides-Extra: docs
67
67
  Requires-Dist: Sphinx<8.3,>=7.4; extra == "docs"