siliconcompiler 0.34.0__py3-none-any.whl → 0.34.2__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 (114) hide show
  1. siliconcompiler/__init__.py +14 -2
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/_common.py +1 -1
  4. siliconcompiler/apps/sc.py +1 -1
  5. siliconcompiler/apps/sc_issue.py +1 -1
  6. siliconcompiler/apps/sc_remote.py +3 -3
  7. siliconcompiler/apps/sc_show.py +3 -3
  8. siliconcompiler/apps/utils/replay.py +4 -4
  9. siliconcompiler/checklist.py +203 -2
  10. siliconcompiler/constraints/__init__.py +17 -0
  11. siliconcompiler/constraints/asic_component.py +378 -0
  12. siliconcompiler/constraints/asic_floorplan.py +449 -0
  13. siliconcompiler/constraints/asic_pins.py +489 -0
  14. siliconcompiler/constraints/asic_timing.py +517 -0
  15. siliconcompiler/core.py +31 -249
  16. siliconcompiler/data/templates/email/general.j2 +3 -3
  17. siliconcompiler/data/templates/email/summary.j2 +1 -1
  18. siliconcompiler/data/templates/issue/README.txt +1 -1
  19. siliconcompiler/data/templates/report/sc_report.j2 +7 -7
  20. siliconcompiler/dependencyschema.py +10 -174
  21. siliconcompiler/design.py +325 -114
  22. siliconcompiler/flowgraph.py +63 -15
  23. siliconcompiler/library.py +133 -0
  24. siliconcompiler/metric.py +94 -72
  25. siliconcompiler/metrics/__init__.py +7 -0
  26. siliconcompiler/metrics/asic.py +245 -0
  27. siliconcompiler/metrics/fpga.py +220 -0
  28. siliconcompiler/optimizer/vizier.py +2 -2
  29. siliconcompiler/package/__init__.py +138 -35
  30. siliconcompiler/package/github.py +6 -10
  31. siliconcompiler/packageschema.py +256 -12
  32. siliconcompiler/pathschema.py +226 -0
  33. siliconcompiler/pdk.py +5 -5
  34. siliconcompiler/project.py +459 -0
  35. siliconcompiler/remote/client.py +18 -12
  36. siliconcompiler/remote/server.py +2 -2
  37. siliconcompiler/report/dashboard/cli/__init__.py +6 -6
  38. siliconcompiler/report/dashboard/cli/board.py +3 -3
  39. siliconcompiler/report/dashboard/web/components/__init__.py +5 -5
  40. siliconcompiler/report/dashboard/web/components/flowgraph.py +4 -4
  41. siliconcompiler/report/dashboard/web/components/graph.py +2 -2
  42. siliconcompiler/report/dashboard/web/state.py +1 -1
  43. siliconcompiler/report/dashboard/web/utils/__init__.py +5 -5
  44. siliconcompiler/report/html_report.py +1 -1
  45. siliconcompiler/report/report.py +4 -4
  46. siliconcompiler/report/summary_table.py +2 -2
  47. siliconcompiler/report/utils.py +5 -5
  48. siliconcompiler/scheduler/docker.py +4 -10
  49. siliconcompiler/scheduler/run_node.py +4 -8
  50. siliconcompiler/scheduler/scheduler.py +18 -24
  51. siliconcompiler/scheduler/schedulernode.py +161 -143
  52. siliconcompiler/scheduler/send_messages.py +3 -3
  53. siliconcompiler/scheduler/slurm.py +5 -3
  54. siliconcompiler/scheduler/taskscheduler.py +10 -8
  55. siliconcompiler/schema/__init__.py +0 -2
  56. siliconcompiler/schema/baseschema.py +148 -26
  57. siliconcompiler/schema/editableschema.py +14 -6
  58. siliconcompiler/schema/journal.py +23 -15
  59. siliconcompiler/schema/namedschema.py +30 -4
  60. siliconcompiler/schema/parameter.py +34 -19
  61. siliconcompiler/schema/parametertype.py +2 -0
  62. siliconcompiler/schema/parametervalue.py +198 -15
  63. siliconcompiler/schema/schema_cfg.py +18 -14
  64. siliconcompiler/schema_obj.py +5 -3
  65. siliconcompiler/tool.py +591 -179
  66. siliconcompiler/tools/__init__.py +2 -0
  67. siliconcompiler/tools/builtin/_common.py +5 -5
  68. siliconcompiler/tools/builtin/concatenate.py +5 -5
  69. siliconcompiler/tools/builtin/minimum.py +4 -4
  70. siliconcompiler/tools/builtin/mux.py +4 -4
  71. siliconcompiler/tools/builtin/nop.py +4 -4
  72. siliconcompiler/tools/builtin/verify.py +7 -7
  73. siliconcompiler/tools/execute/exec_input.py +1 -1
  74. siliconcompiler/tools/genfasm/genfasm.py +1 -6
  75. siliconcompiler/tools/openroad/_apr.py +5 -1
  76. siliconcompiler/tools/openroad/antenna_repair.py +1 -1
  77. siliconcompiler/tools/openroad/macro_placement.py +1 -1
  78. siliconcompiler/tools/openroad/power_grid.py +1 -1
  79. siliconcompiler/tools/openroad/scripts/common/procs.tcl +5 -0
  80. siliconcompiler/tools/opensta/timing.py +26 -3
  81. siliconcompiler/tools/slang/__init__.py +2 -2
  82. siliconcompiler/tools/surfer/__init__.py +0 -0
  83. siliconcompiler/tools/surfer/show.py +53 -0
  84. siliconcompiler/tools/surfer/surfer.py +30 -0
  85. siliconcompiler/tools/vpr/route.py +27 -14
  86. siliconcompiler/tools/vpr/vpr.py +23 -6
  87. siliconcompiler/tools/yosys/__init__.py +1 -1
  88. siliconcompiler/tools/yosys/scripts/procs.tcl +143 -0
  89. siliconcompiler/tools/yosys/{sc_synth_asic.tcl → scripts/sc_synth_asic.tcl} +4 -0
  90. siliconcompiler/tools/yosys/{sc_synth_fpga.tcl → scripts/sc_synth_fpga.tcl} +24 -77
  91. siliconcompiler/tools/yosys/syn_fpga.py +14 -0
  92. siliconcompiler/toolscripts/_tools.json +9 -13
  93. siliconcompiler/toolscripts/rhel9/install-vpr.sh +0 -2
  94. siliconcompiler/toolscripts/ubuntu22/install-surfer.sh +33 -0
  95. siliconcompiler/toolscripts/ubuntu24/install-surfer.sh +33 -0
  96. siliconcompiler/utils/__init__.py +2 -1
  97. siliconcompiler/utils/flowgraph.py +24 -23
  98. siliconcompiler/utils/issue.py +23 -29
  99. siliconcompiler/utils/logging.py +35 -6
  100. siliconcompiler/utils/showtools.py +6 -1
  101. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +15 -25
  102. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +109 -97
  103. siliconcompiler/schema/packageschema.py +0 -101
  104. siliconcompiler/tools/yosys/procs.tcl +0 -71
  105. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +0 -68
  106. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +0 -68
  107. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +0 -68
  108. /siliconcompiler/tools/yosys/{sc_lec.tcl → scripts/sc_lec.tcl} +0 -0
  109. /siliconcompiler/tools/yosys/{sc_screenshot.tcl → scripts/sc_screenshot.tcl} +0 -0
  110. /siliconcompiler/tools/yosys/{syn_strategies.tcl → scripts/syn_strategies.tcl} +0 -0
  111. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
  112. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
  113. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
  114. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/top_level.txt +0 -0
@@ -3,16 +3,21 @@ from siliconcompiler._common import NodeStatus, SiliconCompilerError
3
3
  from siliconcompiler.utils import sc_open
4
4
  from siliconcompiler.schema_obj import SchemaTmp as Schema
5
5
 
6
+ from siliconcompiler.packageschema import PackageSchema
7
+
6
8
  from siliconcompiler.design import DesignSchema
7
9
  from siliconcompiler.record import RecordSchema
8
10
  from siliconcompiler.metric import MetricSchema
9
11
  from siliconcompiler.pdk import PDKSchema
10
12
  from siliconcompiler.flowgraph import FlowgraphSchema
11
- from siliconcompiler.tool import ToolSchema
13
+ from siliconcompiler.tool import ToolSchema, TaskSchema
12
14
  from siliconcompiler.checklist import ChecklistSchema
13
15
  from siliconcompiler.asic import ASICSchema
14
16
  from siliconcompiler.fpga import FPGASchema
15
17
 
18
+ from siliconcompiler.project import Project
19
+ from siliconcompiler.library import LibrarySchema, StdCellLibrarySchema
20
+
16
21
  from siliconcompiler.core import Chip
17
22
 
18
23
  from siliconcompiler._metadata import version as __version__
@@ -31,13 +36,20 @@ __all__ = [
31
36
  "Checklist",
32
37
  "Schema",
33
38
  "sc_open",
39
+
34
40
  "DesignSchema",
41
+ "LibrarySchema",
35
42
  "RecordSchema",
36
43
  "MetricSchema",
37
44
  "PDKSchema",
38
45
  "FlowgraphSchema",
39
46
  "ToolSchema",
47
+ "TaskSchema",
40
48
  "ChecklistSchema",
41
49
  "ASICSchema",
42
- "FPGASchema"
50
+ "FPGASchema",
51
+ "PackageSchema",
52
+
53
+ "Project",
54
+ "StdCellLibrarySchema"
43
55
  ]
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.34.0'
2
+ version = '0.34.2'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -114,7 +114,7 @@ def pick_manifest(chip, src_file=None):
114
114
  if (step, index) in all_manifests[chip.design][jobname]:
115
115
  return all_manifests[chip.design][jobname][(step, index)]
116
116
  else:
117
- chip.logger.error(f'{step}{index} is not a valid node.')
117
+ chip.logger.error(f'{step}/{index} is not a valid node.')
118
118
  return None
119
119
 
120
120
  if (None, None) in all_manifests[chip.design][jobname]:
@@ -19,7 +19,7 @@ def _infer_designname(chip):
19
19
  sourcesets.insert(0, sourceset)
20
20
  for sourceset in sourcesets:
21
21
  for filetype in chip.getkeys('input', sourceset):
22
- all_vals = chip.schema.get('input', sourceset, filetype, field=None).getvalues()
22
+ all_vals = chip.get('input', sourceset, filetype, field=None).getvalues()
23
23
  if all_vals:
24
24
  # just look at first value
25
25
  sources, _, _ = all_vals[0]
@@ -142,7 +142,7 @@ To run a testcase, use:
142
142
  chip.set('arg', 'step', step)
143
143
  chip.set('arg', 'index', index)
144
144
  tool, task = get_tool_task(chip, step, index)
145
- chip.logger.info(f'Preparing run for {step}{index} - {tool}/{task}')
145
+ chip.logger.info(f'Preparing run for {step}/{index} - {tool}/{task}')
146
146
 
147
147
  # Modify run environment to point to extracted files
148
148
  builddir_key = ['option', 'builddir']
@@ -154,10 +154,10 @@ To delete a job, use:
154
154
  elif args['reconnect']:
155
155
  # Start from successors of entry nodes, so entry nodes are not fetched from remote.
156
156
  flow = chip.get('option', 'flow')
157
- entry_nodes = chip.schema.get("flowgraph", flow, field="schema").get_entry_nodes()
157
+ entry_nodes = chip.get("flowgraph", flow, field="schema").get_entry_nodes()
158
158
  for entry_node in entry_nodes:
159
- outputs = chip.schema.get("flowgraph", flow,
160
- field='schema').get_node_outputs(*entry_node)
159
+ outputs = chip.get("flowgraph", flow,
160
+ field='schema').get_node_outputs(*entry_node)
161
161
  chip.set('option', 'from', list(map(lambda node: node[0], outputs)))
162
162
  # Enter the remote run loop.
163
163
  try:
@@ -84,8 +84,8 @@ def main():
84
84
  input_mode = []
85
85
  for fileset in chip.getkeys('input'):
86
86
  for mode in chip.getkeys('input', fileset):
87
- if chip.schema.get('input', fileset, mode, field=None).getvalues():
88
- input_mode = [('input', fileset, mode)]
87
+ if chip.get('input', fileset, mode, field=None).getvalues():
88
+ input_mode.append(('input', fileset, mode))
89
89
 
90
90
  filename = None
91
91
  if input_mode:
@@ -97,7 +97,7 @@ def main():
97
97
  def get_file_from_keys():
98
98
  for ext in check_ext:
99
99
  for key in input_mode:
100
- for files, _, _ in chip.schema.get(*key, field=None).getvalues():
100
+ for files, _, _ in chip.get(*key, field=None).getvalues():
101
101
  for file in files:
102
102
  if get_file_ext(file) == ext:
103
103
  return file
@@ -87,8 +87,8 @@ def main():
87
87
 
88
88
  pythonversion = set()
89
89
  nodes = set()
90
- for version, step, index in chip.schema.get('history', jobname, 'record', 'pythonversion',
91
- field=None).getvalues():
90
+ for version, step, index in chip.get('history', jobname, 'record', 'pythonversion',
91
+ field=None).getvalues():
92
92
  pythonversion.add(version)
93
93
  nodes.add((step, index))
94
94
 
@@ -128,7 +128,7 @@ def main():
128
128
  path = os.path.abspath(args['file'])
129
129
  os.makedirs(os.path.dirname(path), exist_ok=True)
130
130
 
131
- record_schema = chip.schema.get('history', jobname, 'record', field="schema")
131
+ record_schema = chip.get('history', jobname, 'record', field="schema")
132
132
  starttime = datetime.fromtimestamp(
133
133
  record_schema.get_earliest_time(RecordTime.START)).strftime(
134
134
  '%Y-%m-%d %H:%M:%S')
@@ -164,7 +164,7 @@ def main():
164
164
  fd.flush()
165
165
  script = convert_base64(compress(fd.getvalue()))
166
166
 
167
- manifest = convert_base64(compress(json.dumps(chip.schema.getdict(), indent=2)))
167
+ manifest = convert_base64(compress(json.dumps(chip.getdict(), indent=2)))
168
168
 
169
169
  tool_info = []
170
170
  for tool, version in tools.items():
@@ -1,14 +1,215 @@
1
+ import re
2
+
3
+ import os.path
4
+
1
5
  from siliconcompiler.schema import NamedSchema
2
6
  from siliconcompiler.schema import EditableSchema, Parameter, Scope
3
7
  from siliconcompiler.schema.utils import trim
4
8
 
9
+ from siliconcompiler import NodeStatus, utils
10
+
5
11
 
6
12
  class ChecklistSchema(NamedSchema):
7
- def __init__(self, name):
8
- super().__init__(name=name)
13
+ def __init__(self, name=None):
14
+ super().__init__()
15
+ self.set_name(name)
9
16
 
10
17
  schema_checklist(self)
11
18
 
19
+ def check(self, items=None, check_ok=False, require_reports=True):
20
+ '''
21
+ Check items in a checklist.
22
+
23
+ Checks the status of items in a checklist for the standard provided. If
24
+ a specific list of items is unspecified, all items are checked.
25
+
26
+ All items have an associated 'task' parameter, which indicates which
27
+ tasks can be used to automatically validate the item. For an item to be
28
+ checked, all tasks must satisfy the item's criteria, unless waivers are
29
+ provided. In addition, that task must have generated EDA report files
30
+ for each metric in the criteria.
31
+
32
+ For items without an associated task, the only requirement is that at
33
+ least one report has been added to that item.
34
+
35
+ When 'check_ok' is True, every item must also have its 'ok' parameter
36
+ set to True, indicating that a human has reviewed the item.
37
+
38
+ Args:
39
+ items (list of str): Items to check from standard.
40
+ check_ok (bool): Whether to check item 'ok' parameter.
41
+ verbose (bool): Whether to print passing criteria.
42
+ require_reports (bool): Whether to assert the presence of reports.
43
+
44
+ Returns:
45
+ Status of item check.
46
+
47
+ Examples:
48
+ >>> status = chip.check_checklist('d000')
49
+ Returns status.
50
+ '''
51
+ error = False
52
+
53
+ schema_root = self._parent(root=True)
54
+ logger = getattr(schema_root, "logger", None)
55
+ cwd = getattr(schema_root, "cwd", os.getcwd())
56
+
57
+ assert hasattr(schema_root, "history"), f"{schema_root}"
58
+
59
+ if logger:
60
+ logger.info(f'Checking checklist {self.name()}')
61
+
62
+ if items is None:
63
+ items = self.getkeys()
64
+
65
+ # these tasks are recorded by SC so there are no reports
66
+ metrics_without_reports = (
67
+ 'tasktime',
68
+ 'totaltime',
69
+ 'exetime',
70
+ 'memory')
71
+
72
+ for item in items:
73
+ if item not in self.getkeys():
74
+ if logger:
75
+ logger.error(f'{item} is not a check in {self.name()}.')
76
+ error = True
77
+ continue
78
+
79
+ allow_missing_reports = True
80
+
81
+ has_check = False
82
+
83
+ all_criteria = self.get(item, 'criteria')
84
+ for criteria in all_criteria:
85
+ m = re.match(r'^(\w+)\s*([\>\=\<]+)\s*([+\-]?\d+(\.\d+)?(e[+\-]?\d+)?)$',
86
+ criteria.strip())
87
+ if not m:
88
+ raise ValueError(f"Illegal checklist criteria: {criteria}")
89
+
90
+ metric = m.group(1)
91
+ op = m.group(2)
92
+
93
+ if metric not in metrics_without_reports:
94
+ allow_missing_reports = False
95
+
96
+ tasks = self.get(item, 'task')
97
+ for job, step, index in tasks:
98
+ job_data = schema_root.history(job)
99
+
100
+ flow = job_data.get("flowgraph", job_data.get('option', 'flow'), field="schema")
101
+
102
+ if (step, index) not in flow.get_nodes():
103
+ error = True
104
+ if logger:
105
+ logger.error(f'{step}/{index} not found in flowgraph for {job}')
106
+ continue
107
+
108
+ if job_data.get('record', 'status', step=step, index=index) == \
109
+ NodeStatus.SKIPPED:
110
+ if logger:
111
+ logger.warning(f'{step}/{index} was skipped')
112
+ continue
113
+
114
+ has_check = True
115
+
116
+ # Automated checks
117
+ tool = flow.get(step, index, 'tool')
118
+ task = flow.get(step, index, 'task')
119
+
120
+ if metric not in job_data.getkeys("metric"):
121
+ if logger:
122
+ logger.error(f"Criteria must use legal metrics only: {criteria}")
123
+ error = True
124
+ continue
125
+
126
+ if job_data.get("metric", metric, field='type') == 'int':
127
+ goal = int(m.group(3))
128
+ number_format = 'd'
129
+ else:
130
+ goal = float(m.group(3))
131
+
132
+ if goal == 0.0 or (abs(goal) > 1e-3 and abs(goal) < 1e5):
133
+ number_format = '.3f'
134
+ else:
135
+ number_format = '.3e'
136
+
137
+ value = job_data.get('metric', metric, step=step, index=index)
138
+ criteria_ok = utils.safecompare(self, value, op, goal)
139
+ if metric in self.getkeys(item, 'waiver'):
140
+ waivers = self.get(item, 'waiver', metric)
141
+ else:
142
+ waivers = []
143
+
144
+ criteria_str = f'{metric}{op}{goal:{number_format}}'
145
+ compare_str = f'{value:{number_format}}{op}{goal:{number_format}}'
146
+ step_desc = f'job {job} with step {step}/{index} and task {tool}/{task}'
147
+ if not criteria_ok and waivers:
148
+ if logger:
149
+ logger.warning(f'{item} criteria {criteria_str} ({compare_str}) unmet '
150
+ f'by {step_desc}, but found waivers.')
151
+ elif not criteria_ok:
152
+ if logger:
153
+ logger.error(f'{item} criteria {criteria_str} ({compare_str}) unmet '
154
+ f'by {step_desc}.')
155
+ error = True
156
+ elif criteria_ok:
157
+ if logger:
158
+ logger.info(f'{item} criteria {criteria_str} met by {step_desc}.')
159
+
160
+ has_reports = \
161
+ job_data.valid('tool', tool, 'task', task, 'report', metric) and \
162
+ job_data.get('tool', tool, 'task', task, 'report', metric,
163
+ step=step, index=index)
164
+
165
+ if allow_missing_reports and not has_reports:
166
+ # No reports available and it is allowed
167
+ continue
168
+
169
+ reports = []
170
+ try:
171
+ if has_reports:
172
+ reports = job_data.find_files(
173
+ 'tool', tool, 'task', task, 'report', metric,
174
+ step=step, index=index,
175
+ missing_ok=not require_reports)
176
+ except FileNotFoundError:
177
+ reports = []
178
+ continue
179
+
180
+ if require_reports and not reports:
181
+ if logger:
182
+ logger.error(f'No reports generated for metric {metric} in '
183
+ f'{step_desc}')
184
+ error = True
185
+
186
+ for report in reports:
187
+ if not report:
188
+ continue
189
+
190
+ report = os.path.relpath(report, cwd)
191
+ if report not in self.get(item, 'report'):
192
+ self.add(item, 'report', report)
193
+
194
+ if has_check:
195
+ if require_reports and \
196
+ not allow_missing_reports and \
197
+ not self.get(item, 'report'):
198
+ # TODO: validate that report exists?
199
+ if logger:
200
+ logger.error(f'No report documenting item {item}')
201
+ error = True
202
+
203
+ if check_ok and not self.get(item, 'ok'):
204
+ if logger:
205
+ logger.error(f"Item {item} 'ok' field not checked")
206
+ error = True
207
+
208
+ if not error and logger:
209
+ logger.info('Check succeeded!')
210
+
211
+ return not error
212
+
12
213
 
13
214
  ############################################
14
215
  # Design Checklist
@@ -0,0 +1,17 @@
1
+ from siliconcompiler.constraints.asic_timing import \
2
+ ASICTimingConstraintSchema, ASICTimingScenarioSchema
3
+ from siliconcompiler.constraints.asic_floorplan import ASICAreaConstraint
4
+ from siliconcompiler.constraints.asic_pins import \
5
+ ASICPinConstraint, ASICPinConstraints
6
+ from siliconcompiler.constraints.asic_component import \
7
+ ASICComponentConstraint, ASICComponentConstraints
8
+
9
+ __all__ = [
10
+ "ASICTimingConstraintSchema",
11
+ "ASICTimingScenarioSchema",
12
+ "ASICAreaConstraint",
13
+ "ASICPinConstraint",
14
+ "ASICPinConstraints",
15
+ "ASICComponentConstraint",
16
+ "ASICComponentConstraints"
17
+ ]