siliconcompiler 0.28.3__py3-none-any.whl → 0.28.5__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.
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +88 -56
- siliconcompiler/apps/sc.py +33 -14
- siliconcompiler/apps/sc_dashboard.py +17 -10
- siliconcompiler/apps/sc_show.py +17 -15
- siliconcompiler/core.py +95 -55
- siliconcompiler/flows/drcflow.py +13 -0
- siliconcompiler/flows/interposerflow.py +17 -0
- siliconcompiler/fpgas/vpr_example.py +8 -0
- siliconcompiler/libs/interposer.py +8 -0
- siliconcompiler/package.py +3 -2
- siliconcompiler/pdks/interposer.py +8 -0
- siliconcompiler/remote/schema.py +11 -1
- siliconcompiler/remote/server.py +7 -2
- siliconcompiler/report/dashboard/__init__.py +9 -0
- siliconcompiler/report/dashboard/components/__init__.py +13 -1
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph.py +4 -3
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_node_tab.py +4 -1
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_sac_tabs.py +4 -1
- siliconcompiler/report/dashboard/state.py +3 -1
- siliconcompiler/report/summary_table.py +1 -2
- siliconcompiler/report/utils.py +1 -2
- siliconcompiler/scheduler/__init__.py +95 -0
- siliconcompiler/schema/schema_cfg.py +15 -3
- siliconcompiler/schema/schema_obj.py +51 -1
- siliconcompiler/sphinx_ext/dynamicgen.py +6 -0
- siliconcompiler/targets/interposer_demo.py +56 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +2 -0
- siliconcompiler/tools/_common/__init__.py +44 -6
- siliconcompiler/tools/_common/asic.py +79 -23
- siliconcompiler/tools/genfasm/genfasm.py +7 -0
- siliconcompiler/tools/ghdl/convert.py +7 -0
- siliconcompiler/tools/klayout/convert_drc_db.py +60 -0
- siliconcompiler/tools/klayout/drc.py +156 -0
- siliconcompiler/tools/klayout/export.py +9 -4
- siliconcompiler/tools/klayout/klayout.py +0 -1
- siliconcompiler/tools/klayout/klayout_convert_drc_db.py +182 -0
- siliconcompiler/tools/klayout/klayout_export.py +3 -0
- siliconcompiler/tools/klayout/klayout_utils.py +8 -2
- siliconcompiler/tools/klayout/operations.py +2 -0
- siliconcompiler/tools/klayout/screenshot.py +2 -0
- siliconcompiler/tools/klayout/show.py +4 -4
- siliconcompiler/tools/magic/drc.py +21 -0
- siliconcompiler/tools/magic/extspice.py +21 -0
- siliconcompiler/tools/magic/magic.py +29 -0
- siliconcompiler/tools/magic/sc_drc.tcl +2 -12
- siliconcompiler/tools/magic/sc_extspice.tcl +3 -15
- siliconcompiler/tools/openroad/metrics.py +45 -0
- siliconcompiler/tools/openroad/openroad.py +47 -2
- siliconcompiler/tools/openroad/rdlroute.py +97 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +16 -1
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +55 -9
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +0 -159
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +3 -1
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +184 -0
- siliconcompiler/tools/openroad/scripts/sc_report.tcl +170 -0
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +8 -2
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +0 -5
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +36 -6
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +11 -1
- siliconcompiler/tools/surelog/__init__.py +12 -0
- siliconcompiler/tools/verilator/compile.py +27 -0
- siliconcompiler/tools/verilator/verilator.py +9 -0
- siliconcompiler/tools/vpr/vpr.py +18 -0
- siliconcompiler/tools/xyce/__init__.py +1 -1
- siliconcompiler/tools/yosys/{syn_asic_fpga_shared.tcl → procs.tcl} +23 -0
- siliconcompiler/tools/yosys/sc_screenshot.tcl +104 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +7 -9
- siliconcompiler/tools/yosys/screenshot.py +153 -0
- siliconcompiler/tools/yosys/syn_asic.py +3 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +1 -3
- siliconcompiler/tools/yosys/syn_fpga.tcl +3 -2
- siliconcompiler/toolscripts/_tools.json +5 -6
- siliconcompiler/toolscripts/rhel8/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/rhel9/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +5 -5
- siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +2 -2
- siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +2 -2
- siliconcompiler/utils/__init__.py +30 -1
- siliconcompiler/utils/showtools.py +4 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/METADATA +18 -5
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/RECORD +86 -72
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/top_level.txt +0 -0
siliconcompiler/remote/schema.py
CHANGED
|
@@ -2,7 +2,7 @@ from siliconcompiler.schema.schema_cfg import scparam
|
|
|
2
2
|
from siliconcompiler.schema import Schema
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
SCHEMA_VERSION = '0.0.
|
|
5
|
+
SCHEMA_VERSION = '0.0.2'
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def schema_cfg():
|
|
@@ -93,6 +93,16 @@ def schema_cfg():
|
|
|
93
93
|
schelp="""
|
|
94
94
|
Provides explicit control over the level of debug logging printed.""")
|
|
95
95
|
|
|
96
|
+
scparam(cfg, ['option', 'checkinterval'],
|
|
97
|
+
sctype='int',
|
|
98
|
+
defvalue=30,
|
|
99
|
+
shorthelp="Interval for client",
|
|
100
|
+
switch="-checkinterval <int>",
|
|
101
|
+
example=["cli: -checkinterval 10",
|
|
102
|
+
"api: chip.set('option', 'checkinterval', 10)"],
|
|
103
|
+
schelp="""
|
|
104
|
+
Interval between checks to announce to clients""")
|
|
105
|
+
|
|
96
106
|
return cfg
|
|
97
107
|
|
|
98
108
|
|
siliconcompiler/remote/server.py
CHANGED
|
@@ -239,7 +239,7 @@ class Server:
|
|
|
239
239
|
|
|
240
240
|
# Return a response to the client.
|
|
241
241
|
return web.json_response({'message': f"Starting job: {job_hash}",
|
|
242
|
-
'interval':
|
|
242
|
+
'interval': self.checkinterval,
|
|
243
243
|
'job_hash': job_hash})
|
|
244
244
|
|
|
245
245
|
####################
|
|
@@ -375,7 +375,7 @@ class Server:
|
|
|
375
375
|
'sc_schema': sc_schema_version,
|
|
376
376
|
'sc_server': Server.__version__,
|
|
377
377
|
},
|
|
378
|
-
'progress_interval':
|
|
378
|
+
'progress_interval': self.checkinterval
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
username = job_params['username']
|
|
@@ -490,6 +490,11 @@ class Server:
|
|
|
490
490
|
# Ensure that NFS mounting path is absolute.
|
|
491
491
|
return os.path.abspath(self.get('option', 'nfsmount'))
|
|
492
492
|
|
|
493
|
+
###################
|
|
494
|
+
@property
|
|
495
|
+
def checkinterval(self):
|
|
496
|
+
return self.get('option', 'checkinterval')
|
|
497
|
+
|
|
493
498
|
def get(self, *keypath, field='value'):
|
|
494
499
|
return self.schema.get(*keypath, field=field)
|
|
495
500
|
|
|
@@ -12,6 +12,7 @@ import atexit
|
|
|
12
12
|
import shutil
|
|
13
13
|
import fasteners
|
|
14
14
|
import signal
|
|
15
|
+
import socketserver
|
|
15
16
|
|
|
16
17
|
from siliconcompiler.report.dashboard import utils
|
|
17
18
|
|
|
@@ -25,6 +26,8 @@ class Dashboard():
|
|
|
25
26
|
pass
|
|
26
27
|
|
|
27
28
|
def __init__(self, chip, port=None, graph_chips=None):
|
|
29
|
+
if not port:
|
|
30
|
+
port = Dashboard.get_next_port()
|
|
28
31
|
if not port:
|
|
29
32
|
port = Dashboard.__port
|
|
30
33
|
|
|
@@ -172,3 +175,9 @@ class Dashboard():
|
|
|
172
175
|
|
|
173
176
|
if os.path.exists(self.__directory):
|
|
174
177
|
shutil.rmtree(self.__directory)
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def get_next_port():
|
|
181
|
+
with socketserver.TCPServer(("localhost", 0), None) as s:
|
|
182
|
+
return s.server_address[1]
|
|
183
|
+
return None
|
|
@@ -194,7 +194,7 @@ def setup_page():
|
|
|
194
194
|
menu_items=SC_MENU)
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
def file_viewer(chip, path, header_col_width=0.89):
|
|
197
|
+
def file_viewer(chip, path, page_key=None, header_col_width=0.89):
|
|
198
198
|
if not path:
|
|
199
199
|
streamlit.error('Select a file')
|
|
200
200
|
return
|
|
@@ -243,14 +243,25 @@ def file_viewer(chip, path, header_col_width=0.89):
|
|
|
243
243
|
|
|
244
244
|
file_section = streamlit.container()
|
|
245
245
|
|
|
246
|
+
if page_key:
|
|
247
|
+
if state.get_key(page_key) is None:
|
|
248
|
+
state.set_key(page_key, 1)
|
|
249
|
+
index = state.get_key(page_key)
|
|
250
|
+
else:
|
|
251
|
+
index = 1
|
|
252
|
+
|
|
246
253
|
page = sac.pagination(
|
|
247
254
|
align='center',
|
|
255
|
+
index=index,
|
|
248
256
|
jump=True,
|
|
249
257
|
show_total=True,
|
|
250
258
|
page_size=page_size,
|
|
251
259
|
total=max_pages,
|
|
252
260
|
disabled=max_pages < state.get_key(state.MAX_FILE_LINES_TO_SHOW))
|
|
253
261
|
|
|
262
|
+
if page_key:
|
|
263
|
+
state.set_key(page_key, page)
|
|
264
|
+
|
|
254
265
|
start_idx = (page - 1) * state.get_key(state.MAX_FILE_LINES_TO_SHOW)
|
|
255
266
|
end_idx = start_idx + state.get_key(state.MAX_FILE_LINES_TO_SHOW)
|
|
256
267
|
file_show = file_data[start_idx:end_idx]
|
|
@@ -465,6 +476,7 @@ def node_file_tree_viewer(chip, step, index):
|
|
|
465
476
|
|
|
466
477
|
if selected and os.path.isfile(selected):
|
|
467
478
|
state.set_key(state.SELECTED_FILE, selected)
|
|
479
|
+
state.set_key(state.SELECTED_FILE_PAGE, None)
|
|
468
480
|
|
|
469
481
|
|
|
470
482
|
def node_viewer(chip, step, index, metric_dataframe, height=None):
|
|
@@ -80,9 +80,10 @@ def layout():
|
|
|
80
80
|
components.manifest_viewer(chip)
|
|
81
81
|
|
|
82
82
|
with tabs["File Viewer"]:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
components.file_viewer(
|
|
84
|
+
chip,
|
|
85
|
+
state.get_key(state.SELECTED_FILE),
|
|
86
|
+
page_key=state.SELECTED_FILE_PAGE)
|
|
86
87
|
|
|
87
88
|
if "Design Preview" in tabs:
|
|
88
89
|
with tabs["Design Preview"]:
|
|
@@ -103,7 +103,10 @@ def layout():
|
|
|
103
103
|
components.manifest_viewer(chip)
|
|
104
104
|
|
|
105
105
|
if tab_selected == "File Viewer":
|
|
106
|
-
components.file_viewer(
|
|
106
|
+
components.file_viewer(
|
|
107
|
+
chip,
|
|
108
|
+
state.get_key(state.SELECTED_FILE),
|
|
109
|
+
page_key=state.SELECTED_FILE_PAGE)
|
|
107
110
|
|
|
108
111
|
if tab_selected == "Design Preview":
|
|
109
112
|
components.file_viewer(chip, f'{chip.getworkdir()}/{chip.design}.png')
|
|
@@ -96,7 +96,10 @@ def layout():
|
|
|
96
96
|
components.manifest_viewer(chip)
|
|
97
97
|
|
|
98
98
|
if tab_selected == "File Viewer":
|
|
99
|
-
components.file_viewer(
|
|
99
|
+
components.file_viewer(
|
|
100
|
+
chip,
|
|
101
|
+
state.get_key(state.SELECTED_FILE),
|
|
102
|
+
page_key=state.SELECTED_FILE_PAGE)
|
|
100
103
|
|
|
101
104
|
if tab_selected == "Design Preview":
|
|
102
105
|
components.file_viewer(chip, f'{chip.getworkdir()}/{chip.design}.png')
|
|
@@ -16,6 +16,7 @@ SELECTED_FLOWGRAPH_NODE = "selected_flowgraph_node"
|
|
|
16
16
|
SELECTED_SELECTOR_NODE = "selected_selector_node"
|
|
17
17
|
NODE_SOURCE = "node_source"
|
|
18
18
|
SELECTED_FILE = "selected_file"
|
|
19
|
+
SELECTED_FILE_PAGE = "selected_file_page"
|
|
19
20
|
LOADED_CHIPS = "loaded_chips"
|
|
20
21
|
UI_WIDTH = "ui_width"
|
|
21
22
|
MANIFEST_FILE = "manifest_file"
|
|
@@ -73,6 +74,7 @@ def init():
|
|
|
73
74
|
_add_default(SELECTED_SELECTOR_NODE, None)
|
|
74
75
|
_add_default(NODE_SOURCE, None)
|
|
75
76
|
_add_default(SELECTED_FILE, None)
|
|
77
|
+
_add_default(SELECTED_FILE_PAGE, None)
|
|
76
78
|
_add_default(LOADED_CHIPS, {})
|
|
77
79
|
_add_default(MANIFEST_FILE, None)
|
|
78
80
|
_add_default(MANIFEST_LOCK, None)
|
|
@@ -80,7 +82,7 @@ def init():
|
|
|
80
82
|
_add_default(IS_RUNNING, False)
|
|
81
83
|
_add_default(GRAPH_JOBS, None)
|
|
82
84
|
_add_default(UI_WIDTH, None)
|
|
83
|
-
_add_default(APP_LAYOUT, "
|
|
85
|
+
_add_default(APP_LAYOUT, "vertical_flowgraph_sac_tabs")
|
|
84
86
|
_add_default(APP_RERUN, None)
|
|
85
87
|
_add_default(APP_RUNNING_REFRESH, 2 * 1000)
|
|
86
88
|
_add_default(APP_STOPPED_REFRESH, 30 * 1000)
|
|
@@ -12,10 +12,9 @@ def _show_summary_table(chip, flow, flowgraph_nodes, show_all_indices):
|
|
|
12
12
|
'''
|
|
13
13
|
|
|
14
14
|
# Display data
|
|
15
|
-
max_line_width = 135
|
|
16
15
|
column_width = 15
|
|
17
16
|
|
|
18
|
-
max_line_width = max(
|
|
17
|
+
max_line_width = max(2 * column_width, int(0.95*shutil.get_terminal_size().columns))
|
|
19
18
|
|
|
20
19
|
nodes, _, metrics, metrics_unit, metrics_to_show, _ = \
|
|
21
20
|
_collect_data(chip, flow, flowgraph_nodes)
|
siliconcompiler/report/utils.py
CHANGED
|
@@ -143,8 +143,7 @@ def _get_flowgraph_path(chip, flow, nodes_to_execute, only_include_successful=Fa
|
|
|
143
143
|
end_nodes = _get_flowgraph_exit_nodes(chip, flow, steps=flowgraph_steps)
|
|
144
144
|
for node in end_nodes:
|
|
145
145
|
if only_include_successful:
|
|
146
|
-
if chip.get('record', 'status', step=node[0], index=node[1])
|
|
147
|
-
NodeStatus.SUCCESS:
|
|
146
|
+
if NodeStatus.is_success(chip.get('record', 'status', step=node[0], index=node[1])):
|
|
148
147
|
selected_nodes.add(node)
|
|
149
148
|
to_search.append(node)
|
|
150
149
|
else:
|
|
@@ -688,7 +688,9 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
|
|
|
688
688
|
runtime_options = getattr(chip._get_tool_module(step, index), 'runtime_options', None)
|
|
689
689
|
if runtime_options:
|
|
690
690
|
try:
|
|
691
|
+
chip.schema._start_record_access()
|
|
691
692
|
cmdlist.extend(parse_options(runtime_options(chip)))
|
|
693
|
+
chip.schema._stop_record_access()
|
|
692
694
|
except Exception as e:
|
|
693
695
|
chip.logger.error(f'Failed to get runtime options for {tool}/{task}')
|
|
694
696
|
raise e
|
|
@@ -898,6 +900,7 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
|
|
|
898
900
|
|
|
899
901
|
cmd_start_time = time.time()
|
|
900
902
|
proc = subprocess.Popen(cmdlist,
|
|
903
|
+
stdin=subprocess.DEVNULL,
|
|
901
904
|
stdout=stdout_writer,
|
|
902
905
|
stderr=stderr_writer,
|
|
903
906
|
preexec_fn=preexec_fn)
|
|
@@ -982,7 +985,9 @@ def _post_process(chip, step, index):
|
|
|
982
985
|
func = getattr(chip._get_task_module(step, index, flow=flow), 'post_process', None)
|
|
983
986
|
if func:
|
|
984
987
|
try:
|
|
988
|
+
chip.schema._start_record_access()
|
|
985
989
|
func(chip)
|
|
990
|
+
chip.schema._stop_record_access()
|
|
986
991
|
except Exception as e:
|
|
987
992
|
chip.logger.error(f'Failed to run post-process for {tool}/{task}.')
|
|
988
993
|
print_traceback(chip, e)
|
|
@@ -1075,7 +1080,9 @@ def _pre_process(chip, step, index):
|
|
|
1075
1080
|
func = getattr(chip._get_task_module(step, index, flow=flow), 'pre_process', None)
|
|
1076
1081
|
if func:
|
|
1077
1082
|
try:
|
|
1083
|
+
chip.schema._start_record_access()
|
|
1078
1084
|
func(chip)
|
|
1085
|
+
chip.schema._stop_record_access()
|
|
1079
1086
|
except Exception as e:
|
|
1080
1087
|
chip.logger.error(f"Pre-processing failed for '{tool}/{task}'.")
|
|
1081
1088
|
raise e
|
|
@@ -1087,6 +1094,8 @@ def _pre_process(chip, step, index):
|
|
|
1087
1094
|
def _set_env_vars(chip, step, index):
|
|
1088
1095
|
flow = chip.get('option', 'flow')
|
|
1089
1096
|
tool, task = get_tool_task(chip, step, index, flow)
|
|
1097
|
+
|
|
1098
|
+
chip.schema._start_record_access()
|
|
1090
1099
|
# License file configuration.
|
|
1091
1100
|
for item in chip.getkeys('tool', tool, 'licenseserver'):
|
|
1092
1101
|
license_file = chip.get('tool', tool, 'licenseserver', item, step=step, index=index)
|
|
@@ -1099,6 +1108,8 @@ def _set_env_vars(chip, step, index):
|
|
|
1099
1108
|
if val:
|
|
1100
1109
|
os.environ[item] = val
|
|
1101
1110
|
|
|
1111
|
+
chip.schema._stop_record_access()
|
|
1112
|
+
|
|
1102
1113
|
|
|
1103
1114
|
def _check_tool_version(chip, step, index, run_func=None):
|
|
1104
1115
|
'''
|
|
@@ -1118,6 +1129,7 @@ def _check_tool_version(chip, step, index, run_func=None):
|
|
|
1118
1129
|
cmdlist = [exe]
|
|
1119
1130
|
cmdlist.extend(veropt)
|
|
1120
1131
|
proc = subprocess.run(cmdlist,
|
|
1132
|
+
stdin=subprocess.DEVNULL,
|
|
1121
1133
|
stdout=subprocess.PIPE,
|
|
1122
1134
|
stderr=subprocess.STDOUT,
|
|
1123
1135
|
universal_newlines=True)
|
|
@@ -1189,6 +1201,9 @@ def _hash_files(chip, step, index, setup=False):
|
|
|
1189
1201
|
|
|
1190
1202
|
|
|
1191
1203
|
def _finalizenode(chip, step, index, replay):
|
|
1204
|
+
if chip.schema._do_record_access():
|
|
1205
|
+
assert_required_accesses(chip, step, index)
|
|
1206
|
+
|
|
1192
1207
|
flow = chip.get('option', 'flow')
|
|
1193
1208
|
tool, task = get_tool_task(chip, step, index, flow)
|
|
1194
1209
|
quiet = (
|
|
@@ -1284,6 +1299,86 @@ def assert_output_files(chip, step, index):
|
|
|
1284
1299
|
chip=chip)
|
|
1285
1300
|
|
|
1286
1301
|
|
|
1302
|
+
def assert_required_accesses(chip, step, index):
|
|
1303
|
+
flow = chip.get('option', 'flow')
|
|
1304
|
+
jobname = chip.get('option', 'jobname')
|
|
1305
|
+
tool, task = get_tool_task(chip, step, index, flow)
|
|
1306
|
+
|
|
1307
|
+
if tool == 'builtin':
|
|
1308
|
+
return
|
|
1309
|
+
|
|
1310
|
+
gets = chip.schema._get_record_access()
|
|
1311
|
+
logfile = os.path.join(
|
|
1312
|
+
chip.getworkdir(jobname=jobname, step=step, index=index),
|
|
1313
|
+
f'{step}.log')
|
|
1314
|
+
|
|
1315
|
+
with sc_open(logfile) as f:
|
|
1316
|
+
for line in f:
|
|
1317
|
+
if line.startswith(Schema._RECORD_ACCESS_IDENTIFIER):
|
|
1318
|
+
key = line[len(Schema._RECORD_ACCESS_IDENTIFIER):].strip().split(',')
|
|
1319
|
+
if chip.valid(*key, check_complete=True):
|
|
1320
|
+
gets.add(tuple(key))
|
|
1321
|
+
|
|
1322
|
+
def get_value(*key):
|
|
1323
|
+
if chip.get(*key, field='pernode') == 'never':
|
|
1324
|
+
return chip.get(*key)
|
|
1325
|
+
else:
|
|
1326
|
+
return chip.get(*key, step=step, index=index)
|
|
1327
|
+
|
|
1328
|
+
getkeys = set()
|
|
1329
|
+
# Remove keys with empty values
|
|
1330
|
+
for key in set(sorted(gets)):
|
|
1331
|
+
if get_value(*key):
|
|
1332
|
+
getkeys.add(key)
|
|
1333
|
+
|
|
1334
|
+
# Remove keys that dont matter
|
|
1335
|
+
exempt = [
|
|
1336
|
+
('design',),
|
|
1337
|
+
('arg', 'step'), ('arg', 'index'),
|
|
1338
|
+
('option', 'jobname'), ('option', 'flow'), ('option', 'strict'), ('option', 'builddir'),
|
|
1339
|
+
('option', 'quiet'),
|
|
1340
|
+
('tool', tool, 'exe'),
|
|
1341
|
+
('tool', tool, 'task', task, 'require'),
|
|
1342
|
+
('tool', tool, 'task', task, 'threads'),
|
|
1343
|
+
('flowgraph', flow, step, index, 'tool'), ('flowgraph', flow, step, index, 'task'),
|
|
1344
|
+
('flowgraph', flow, step, index, 'taskmodule')]
|
|
1345
|
+
for key in chip.getkeys('metric'):
|
|
1346
|
+
exempt.append(('metric', key))
|
|
1347
|
+
for key in chip.getkeys('tool', tool, 'task', task, 'report'):
|
|
1348
|
+
exempt.append(('tool', tool, 'task', task, 'report', key))
|
|
1349
|
+
|
|
1350
|
+
# Get exempted keys from task
|
|
1351
|
+
func = getattr(chip._get_task_module(step, index, flow=flow), 'exempt_keys', None)
|
|
1352
|
+
if func:
|
|
1353
|
+
# No need for try / except since this must work properly
|
|
1354
|
+
exempt.extend(func(chip))
|
|
1355
|
+
|
|
1356
|
+
required = set(
|
|
1357
|
+
[tuple(key.split(',')) for key in chip.get('tool', tool, 'task', task, 'require',
|
|
1358
|
+
step=step, index=index)])
|
|
1359
|
+
|
|
1360
|
+
for key in set(exempt):
|
|
1361
|
+
if key in getkeys:
|
|
1362
|
+
getkeys.remove(key)
|
|
1363
|
+
if key in required:
|
|
1364
|
+
required.remove(key)
|
|
1365
|
+
|
|
1366
|
+
excess_require = required.difference(getkeys)
|
|
1367
|
+
if True:
|
|
1368
|
+
for key in sorted(excess_require):
|
|
1369
|
+
chip.logger.error(f"{step}{index} does not require requirement: {','.join(key)}")
|
|
1370
|
+
missing_require = getkeys.difference(required)
|
|
1371
|
+
for key in sorted(missing_require):
|
|
1372
|
+
chip.logger.error(f"{step}{index} has an unexpressed requirement: "
|
|
1373
|
+
f"{','.join(key)} = {get_value(*key)}")
|
|
1374
|
+
|
|
1375
|
+
if missing_require:
|
|
1376
|
+
raise SiliconCompilerError(
|
|
1377
|
+
f'Requirements for {step}{index} does not match access list: '
|
|
1378
|
+
f'{", ".join([",".join(key) for key in sorted(missing_require)])}',
|
|
1379
|
+
chip=chip)
|
|
1380
|
+
|
|
1381
|
+
|
|
1287
1382
|
def _reset_flow_nodes(chip, flow, nodes_to_execute):
|
|
1288
1383
|
# Reset flowgraph/records/metrics by probing build directory. We need
|
|
1289
1384
|
# to set values to None for steps we may re-run so that merging
|
|
@@ -10,7 +10,7 @@ try:
|
|
|
10
10
|
except ImportError:
|
|
11
11
|
from siliconcompiler.schema.utils import trim
|
|
12
12
|
|
|
13
|
-
SCHEMA_VERSION = '0.48.
|
|
13
|
+
SCHEMA_VERSION = '0.48.4'
|
|
14
14
|
|
|
15
15
|
#############################################################################
|
|
16
16
|
# PARAM DEFINITION
|
|
@@ -1252,7 +1252,6 @@ def schema_datasheet(cfg, name='default', mode='default'):
|
|
|
1252
1252
|
# Package Description
|
|
1253
1253
|
#########################
|
|
1254
1254
|
|
|
1255
|
-
# high level description
|
|
1256
1255
|
scparam(cfg, ['datasheet', 'package', name, 'type'],
|
|
1257
1256
|
sctype='enum',
|
|
1258
1257
|
enum=['bga', 'lga', 'csp', 'qfn', 'qfp', 'sop', 'die', 'wafer'],
|
|
@@ -1263,6 +1262,16 @@ def schema_datasheet(cfg, name='default', mode='default'):
|
|
|
1263
1262
|
"api: chip.set('datasheet', 'package', 'abcd', 'type', 'bga')"],
|
|
1264
1263
|
schelp="""Package type specified on a named package basis.""")
|
|
1265
1264
|
|
|
1265
|
+
scparam(cfg, ['datasheet', 'package', name, 'footprint'],
|
|
1266
|
+
sctype='str',
|
|
1267
|
+
shorthelp="Datasheet: package footprint",
|
|
1268
|
+
switch="-datasheet_package_footprint 'name <str>'",
|
|
1269
|
+
example=[
|
|
1270
|
+
"cli: -datasheet_package_footprint 'abcd soic8'",
|
|
1271
|
+
"api: chip.set('datasheet', 'package', 'abcd', 'footprint', 'soic8')"],
|
|
1272
|
+
schelp="""Package footprint name. The name of the footprint can be a standard
|
|
1273
|
+
footprint name or a reference designator from a footprint library.""")
|
|
1274
|
+
|
|
1266
1275
|
scparam(cfg, ['datasheet', 'package', name, 'drawing'],
|
|
1267
1276
|
sctype='[file]',
|
|
1268
1277
|
shorthelp="Datasheet: package drawing",
|
|
@@ -2158,7 +2167,10 @@ def schema_metric(cfg, step='default', index='default'):
|
|
|
2158
2167
|
device families.""")
|
|
2159
2168
|
|
|
2160
2169
|
metrics = {'cellarea': 'cell area (ignoring fillers)',
|
|
2161
|
-
'totalarea': 'physical die area'
|
|
2170
|
+
'totalarea': 'physical die area',
|
|
2171
|
+
'macroarea': 'macro cell area',
|
|
2172
|
+
'padcellarea': 'io pad cell area',
|
|
2173
|
+
'stdcellarea': 'standard cell area'}
|
|
2162
2174
|
|
|
2163
2175
|
for item, val in metrics.items():
|
|
2164
2176
|
scparam(cfg, ['metric', item],
|
|
@@ -61,6 +61,8 @@ class Schema:
|
|
|
61
61
|
logger (logging.Logger): instance of the parent logger if available
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
|
+
_RECORD_ACCESS_IDENTIFIER = "SC_CFG_ACCESS_KEY"
|
|
65
|
+
|
|
64
66
|
# Special key in node dict that represents a value corresponds to a
|
|
65
67
|
# global default for all steps/indices.
|
|
66
68
|
GLOBAL_KEY = 'global'
|
|
@@ -70,6 +72,9 @@ class Schema:
|
|
|
70
72
|
if cfg is not None and manifest is not None:
|
|
71
73
|
raise ValueError('You may not specify both cfg and manifest')
|
|
72
74
|
|
|
75
|
+
# Use during testing to record calls to Schema.get
|
|
76
|
+
self._init_record_access()
|
|
77
|
+
|
|
73
78
|
self._init_logger(logger)
|
|
74
79
|
|
|
75
80
|
self._stop_journal()
|
|
@@ -256,6 +261,10 @@ class Schema:
|
|
|
256
261
|
|
|
257
262
|
See :meth:`~siliconcompiler.core.Chip.get` for detailed documentation.
|
|
258
263
|
"""
|
|
264
|
+
|
|
265
|
+
if self.__record_access["recording"]:
|
|
266
|
+
self.__record_access["record"].add(tuple(keypath))
|
|
267
|
+
|
|
259
268
|
# Prevent accidental modifications of the schema content by not passing a reference
|
|
260
269
|
return copy.copy(self.__get(*keypath, field=field, job=job, step=step, index=index))
|
|
261
270
|
|
|
@@ -1087,7 +1096,9 @@ class Schema:
|
|
|
1087
1096
|
|
|
1088
1097
|
if template:
|
|
1089
1098
|
fout.write(template.render(manifest_dict='\n'.join(tcl_set_cmds),
|
|
1090
|
-
scroot=os.path.abspath(PACKAGE_ROOT)
|
|
1099
|
+
scroot=os.path.abspath(PACKAGE_ROOT),
|
|
1100
|
+
record_access=self._do_record_access(),
|
|
1101
|
+
record_access_id=Schema._RECORD_ACCESS_IDENTIFIER))
|
|
1091
1102
|
else:
|
|
1092
1103
|
for cmd in tcl_set_cmds:
|
|
1093
1104
|
fout.write(cmd + '\n')
|
|
@@ -1305,6 +1316,45 @@ class Schema:
|
|
|
1305
1316
|
except Exception as e:
|
|
1306
1317
|
self.logger.error(f'Exception: {e}')
|
|
1307
1318
|
|
|
1319
|
+
#######################################
|
|
1320
|
+
def _do_record_access(self):
|
|
1321
|
+
'''
|
|
1322
|
+
Determine if Schema should record calls to .get
|
|
1323
|
+
'''
|
|
1324
|
+
return False
|
|
1325
|
+
|
|
1326
|
+
#######################################
|
|
1327
|
+
def _init_record_access(self):
|
|
1328
|
+
'''
|
|
1329
|
+
Initialize record access data record
|
|
1330
|
+
'''
|
|
1331
|
+
self.__record_access = {
|
|
1332
|
+
"do": self._do_record_access(),
|
|
1333
|
+
"recording": False,
|
|
1334
|
+
"record": set()
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
#######################################
|
|
1338
|
+
def _start_record_access(self):
|
|
1339
|
+
'''
|
|
1340
|
+
Start recording calls to .get
|
|
1341
|
+
'''
|
|
1342
|
+
self.__record_access["recording"] = True
|
|
1343
|
+
|
|
1344
|
+
#######################################
|
|
1345
|
+
def _stop_record_access(self):
|
|
1346
|
+
'''
|
|
1347
|
+
Stop recording calls to .get
|
|
1348
|
+
'''
|
|
1349
|
+
self.__record_access["recording"] = False
|
|
1350
|
+
|
|
1351
|
+
#######################################
|
|
1352
|
+
def _get_record_access(self):
|
|
1353
|
+
'''
|
|
1354
|
+
Return calls to record_access
|
|
1355
|
+
'''
|
|
1356
|
+
return self.__record_access["record"].copy()
|
|
1357
|
+
|
|
1308
1358
|
#######################################
|
|
1309
1359
|
def get_default(self, *keypath):
|
|
1310
1360
|
'''Returns default value of a parameter.
|
|
@@ -343,6 +343,8 @@ class DynamicGen(SphinxDirective):
|
|
|
343
343
|
type_heading = "Variables"
|
|
344
344
|
elif type == "file":
|
|
345
345
|
type_heading = "Files"
|
|
346
|
+
elif type == "dir":
|
|
347
|
+
type_heading = "Directories"
|
|
346
348
|
|
|
347
349
|
table = [[strong('Parameters'), strong('Help')]]
|
|
348
350
|
for key, params in cfg.items():
|
|
@@ -657,6 +659,9 @@ class ToolGen(DynamicGen):
|
|
|
657
659
|
'''Display config under `eda, <modname>` in a single table.'''
|
|
658
660
|
cfg = chip.getdict('tool', toolname, 'task', taskname)
|
|
659
661
|
schema = Schema(cfg=cfg)
|
|
662
|
+
for vals, step, index in schema._getvals('require'):
|
|
663
|
+
schema.set('require', sorted(set(vals)),
|
|
664
|
+
step=step, index=index)
|
|
660
665
|
schema.prune()
|
|
661
666
|
pruned = schema.cfg
|
|
662
667
|
table = build_schema_value_table(pruned, self.env.docname,
|
|
@@ -789,6 +794,7 @@ class ToolGen(DynamicGen):
|
|
|
789
794
|
key_path = ['tool', '<tool>', 'task', '<task>']
|
|
790
795
|
self._document_free_params(cfg, 'var', key_path + ['var'], reference_prefix, s)
|
|
791
796
|
self._document_free_params(cfg, 'file', key_path + ['file'], reference_prefix, s)
|
|
797
|
+
self._document_free_params(cfg, 'dir', key_path + ['dir'], reference_prefix, s)
|
|
792
798
|
|
|
793
799
|
def _handle_setup(self, chip, module):
|
|
794
800
|
setup = self.get_setup_method(module)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from siliconcompiler import Chip
|
|
2
|
+
from siliconcompiler.flows import interposerflow, drcflow
|
|
3
|
+
|
|
4
|
+
from lambdapdk import interposer
|
|
5
|
+
from lambdapdk.interposer.libs import bumps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
####################################################
|
|
9
|
+
# Target Setup
|
|
10
|
+
####################################################
|
|
11
|
+
def setup(chip):
|
|
12
|
+
'''
|
|
13
|
+
Interposer Demo Target
|
|
14
|
+
'''
|
|
15
|
+
|
|
16
|
+
# 1. Load PDK, flow, libs
|
|
17
|
+
chip.use(interposer)
|
|
18
|
+
chip.use(bumps)
|
|
19
|
+
chip.use(interposerflow)
|
|
20
|
+
chip.use(drcflow)
|
|
21
|
+
|
|
22
|
+
# 2. Set default targets
|
|
23
|
+
chip.set('option', 'flow', 'interposerflow', clobber=False)
|
|
24
|
+
chip.set('option', 'pdk', 'interposer', clobber=False)
|
|
25
|
+
chip.set('option', 'stackup', '3ML_0400', clobber=False)
|
|
26
|
+
chip.set('option', 'var', 'openroad_libtype', 'none', clobber=False)
|
|
27
|
+
chip.set('option', 'var', 'klayout_libtype', 'none', clobber=False)
|
|
28
|
+
|
|
29
|
+
# 3. Set project specific design choices
|
|
30
|
+
chip.set('asic', 'macrolib', 'interposer_bumps', clobber=False)
|
|
31
|
+
|
|
32
|
+
# 4. get project specific design choices
|
|
33
|
+
chip.set('asic', 'delaymodel', 'nldm', clobber=False)
|
|
34
|
+
|
|
35
|
+
# 5. Timing corners
|
|
36
|
+
chip.set('constraint', 'timing', 'slow', 'libcorner', 'slow', clobber=False)
|
|
37
|
+
chip.set('constraint', 'timing', 'slow', 'pexcorner', 'maximum', clobber=False)
|
|
38
|
+
chip.set('constraint', 'timing', 'slow', 'mode', 'func', clobber=False)
|
|
39
|
+
chip.set('constraint', 'timing', 'slow', 'check', ['setup', 'hold'], clobber=False)
|
|
40
|
+
|
|
41
|
+
chip.set('constraint', 'timing', 'fast', 'libcorner', 'fast', clobber=False)
|
|
42
|
+
chip.set('constraint', 'timing', 'fast', 'pexcorner', 'minimum', clobber=False)
|
|
43
|
+
chip.set('constraint', 'timing', 'fast', 'mode', 'func', clobber=False)
|
|
44
|
+
chip.set('constraint', 'timing', 'fast', 'check', ['setup', 'hold'], clobber=False)
|
|
45
|
+
|
|
46
|
+
chip.set('constraint', 'timing', 'typical', 'libcorner', 'typ', clobber=False)
|
|
47
|
+
chip.set('constraint', 'timing', 'typical', 'pexcorner', 'typical', clobber=False)
|
|
48
|
+
chip.set('constraint', 'timing', 'typical', 'mode', 'func', clobber=False)
|
|
49
|
+
chip.set('constraint', 'timing', 'typical', 'check', ['setup', 'hold'], clobber=False)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
#########################
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
target = Chip('<target>')
|
|
55
|
+
setup(target)
|
|
56
|
+
target.write_manifest('interposer_demo.json')
|
|
@@ -16,6 +16,8 @@ proc sc_cfg_get { args } {
|
|
|
16
16
|
# Refer to global sc_cfg dictionary
|
|
17
17
|
global sc_cfg
|
|
18
18
|
|
|
19
|
+
{% if record_access %}puts "{{ record_access_id }} [join $args ,]"{% endif %}
|
|
20
|
+
|
|
19
21
|
if { ![sc_cfg_exists {*}$args] } {
|
|
20
22
|
throw {FLOW KEYERROR} "key \"$args\" is not in the siliconcompiler configuration"
|
|
21
23
|
}
|