siliconcompiler 0.28.1__py3-none-any.whl → 0.28.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.
- siliconcompiler/_common.py +12 -0
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/sc_dashboard.py +5 -1
- siliconcompiler/apps/sc_install.py +240 -0
- siliconcompiler/apps/sc_remote.py +1 -1
- siliconcompiler/core.py +54 -13
- siliconcompiler/remote/client.py +41 -10
- siliconcompiler/report/__init__.py +1 -1
- siliconcompiler/report/{streamlit_report.py → dashboard/__init__.py} +47 -10
- siliconcompiler/report/dashboard/components/__init__.py +534 -0
- siliconcompiler/report/dashboard/components/flowgraph.py +114 -0
- siliconcompiler/report/dashboard/components/graph.py +208 -0
- siliconcompiler/report/dashboard/layouts/__init__.py +20 -0
- siliconcompiler/report/dashboard/layouts/_common.py +43 -0
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph.py +95 -0
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_node_tab.py +114 -0
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_sac_tabs.py +107 -0
- siliconcompiler/report/dashboard/state.py +215 -0
- siliconcompiler/report/dashboard/utils/__init__.py +73 -0
- siliconcompiler/report/dashboard/utils/file_utils.py +120 -0
- siliconcompiler/report/dashboard/viewer.py +36 -0
- siliconcompiler/report/report.py +22 -4
- siliconcompiler/scheduler/__init__.py +43 -6
- siliconcompiler/schema/schema_obj.py +4 -2
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +6 -5
- siliconcompiler/tools/openroad/floorplan.py +5 -0
- siliconcompiler/tools/openroad/openroad.py +12 -3
- siliconcompiler/tools/openroad/scripts/sc_cts.tcl +18 -13
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +6 -1
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +44 -16
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +10 -10
- siliconcompiler/tools/opensta/scripts/sc_procs.tcl +3 -3
- siliconcompiler/tools/yosys/syn_asic.tcl +1 -1
- siliconcompiler/toolscripts/_tools.json +136 -0
- siliconcompiler/toolscripts/_tools.py +222 -0
- siliconcompiler/toolscripts/rhel8/install-chisel.sh +26 -0
- siliconcompiler/toolscripts/rhel8/install-ghdl.sh +25 -0
- siliconcompiler/toolscripts/rhel8/install-icarus.sh +40 -0
- siliconcompiler/toolscripts/rhel8/install-klayout.sh +17 -0
- siliconcompiler/toolscripts/rhel8/install-magic.sh +26 -0
- siliconcompiler/toolscripts/rhel8/install-montage.sh +5 -0
- siliconcompiler/toolscripts/rhel8/install-netgen.sh +25 -0
- siliconcompiler/toolscripts/rhel8/install-openroad.sh +31 -0
- siliconcompiler/toolscripts/rhel8/install-slang.sh +31 -0
- siliconcompiler/toolscripts/rhel8/install-surelog.sh +32 -0
- siliconcompiler/toolscripts/rhel8/install-sv2v.sh +27 -0
- siliconcompiler/toolscripts/rhel8/install-verible.sh +24 -0
- siliconcompiler/toolscripts/rhel8/install-verilator.sh +40 -0
- siliconcompiler/toolscripts/rhel8/install-xyce.sh +64 -0
- siliconcompiler/toolscripts/rhel8/install-yosys.sh +23 -0
- siliconcompiler/toolscripts/rhel9/install-chisel.sh +26 -0
- siliconcompiler/toolscripts/rhel9/install-ghdl.sh +25 -0
- siliconcompiler/toolscripts/rhel9/install-icarus.sh +40 -0
- siliconcompiler/toolscripts/rhel9/install-klayout.sh +17 -0
- siliconcompiler/toolscripts/rhel9/install-magic.sh +26 -0
- siliconcompiler/toolscripts/rhel9/install-montage.sh +5 -0
- siliconcompiler/toolscripts/rhel9/install-netgen.sh +25 -0
- siliconcompiler/toolscripts/rhel9/install-slang.sh +31 -0
- siliconcompiler/toolscripts/rhel9/install-surelog.sh +32 -0
- siliconcompiler/toolscripts/rhel9/install-sv2v.sh +27 -0
- siliconcompiler/toolscripts/rhel9/install-verible.sh +24 -0
- siliconcompiler/toolscripts/rhel9/install-verilator.sh +40 -0
- siliconcompiler/toolscripts/rhel9/install-xdm.sh +43 -0
- siliconcompiler/toolscripts/rhel9/install-xyce.sh +64 -0
- siliconcompiler/toolscripts/rhel9/install-yosys.sh +23 -0
- siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +49 -0
- siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +35 -0
- siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +26 -0
- siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +25 -0
- siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +25 -0
- siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +22 -0
- siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +29 -0
- siliconcompiler/toolscripts/ubuntu20/install-magic.sh +24 -0
- siliconcompiler/toolscripts/ubuntu20/install-montage.sh +5 -0
- siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +24 -0
- siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +32 -0
- siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +31 -0
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +38 -0
- siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +32 -0
- siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +30 -0
- siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +26 -0
- siliconcompiler/toolscripts/ubuntu20/install-verible.sh +24 -0
- siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +34 -0
- siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +27 -0
- siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +40 -0
- siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +65 -0
- siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +24 -0
- siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +49 -0
- siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +35 -0
- siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +26 -0
- siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +25 -0
- siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +25 -0
- siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +22 -0
- siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +29 -0
- siliconcompiler/toolscripts/ubuntu22/install-magic.sh +24 -0
- siliconcompiler/toolscripts/ubuntu22/install-montage.sh +5 -0
- siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +24 -0
- siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +32 -0
- siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +31 -0
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +28 -0
- siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +32 -0
- siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +25 -0
- siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +26 -0
- siliconcompiler/toolscripts/ubuntu22/install-verible.sh +24 -0
- siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +34 -0
- siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +27 -0
- siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +40 -0
- siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +65 -0
- siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +24 -0
- siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +49 -0
- siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +35 -0
- siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +26 -0
- siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +25 -0
- siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +25 -0
- siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +22 -0
- siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +31 -0
- siliconcompiler/toolscripts/ubuntu24/install-magic.sh +24 -0
- siliconcompiler/toolscripts/ubuntu24/install-montage.sh +5 -0
- siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +24 -0
- siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +32 -0
- siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +31 -0
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +28 -0
- siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +32 -0
- siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +25 -0
- siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +26 -0
- siliconcompiler/toolscripts/ubuntu24/install-verible.sh +24 -0
- siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +34 -0
- siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +27 -0
- siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +40 -0
- siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +65 -0
- siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +24 -0
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/METADATA +7 -6
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/RECORD +139 -29
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/entry_points.txt +1 -0
- siliconcompiler/report/streamlit_viewer.py +0 -944
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.28.1.dist-info → siliconcompiler-0.28.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import streamlit
|
|
5
|
+
import streamlit_javascript
|
|
6
|
+
import fasteners
|
|
7
|
+
|
|
8
|
+
from siliconcompiler import Chip
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DISPLAY_FLOWGRAPH = "show_flowgraph"
|
|
12
|
+
SELECTED_JOB = "selected_job"
|
|
13
|
+
SELECTED_NODE = "selected_node"
|
|
14
|
+
# This is needed until the graph supports setting a selected node
|
|
15
|
+
SELECTED_FLOWGRAPH_NODE = "selected_flowgraph_node"
|
|
16
|
+
SELECTED_SELECTOR_NODE = "selected_selector_node"
|
|
17
|
+
NODE_SOURCE = "node_source"
|
|
18
|
+
SELECTED_FILE = "selected_file"
|
|
19
|
+
LOADED_CHIPS = "loaded_chips"
|
|
20
|
+
UI_WIDTH = "ui_width"
|
|
21
|
+
MANIFEST_FILE = "manifest_file"
|
|
22
|
+
MANIFEST_LOCK = "manifest_lock"
|
|
23
|
+
MANIFEST_TIME = "manifest_time"
|
|
24
|
+
IS_RUNNING = "is_flow_running"
|
|
25
|
+
GRAPH_JOBS = "graph_jobs"
|
|
26
|
+
APP_LAYOUT = "app_layout"
|
|
27
|
+
APP_RERUN = "app_rerun"
|
|
28
|
+
APP_RUNNING_REFRESH = "app_running_refresh"
|
|
29
|
+
APP_STOPPED_REFRESH = "app_stopped_refresh"
|
|
30
|
+
MAX_DICT_ITEMS_TO_SHOW = "max_dict_items"
|
|
31
|
+
MAX_FILE_LINES_TO_SHOW = "max_file_lines"
|
|
32
|
+
SELECT_TAB = "select_tab"
|
|
33
|
+
TAB_INDEX = "tab-index"
|
|
34
|
+
TAB_STATE = "tab-state"
|
|
35
|
+
|
|
36
|
+
_DEBUG = False
|
|
37
|
+
DEVELOPER = False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _add_default(key, value):
|
|
41
|
+
if key not in streamlit.session_state:
|
|
42
|
+
streamlit.session_state[key] = value
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def update_manifest():
|
|
46
|
+
file_time = os.stat(get_key(MANIFEST_FILE)).st_mtime
|
|
47
|
+
|
|
48
|
+
if get_key(MANIFEST_TIME) != file_time:
|
|
49
|
+
chip = Chip(design='')
|
|
50
|
+
|
|
51
|
+
with get_key(MANIFEST_LOCK):
|
|
52
|
+
chip.read_manifest(get_key(MANIFEST_FILE))
|
|
53
|
+
set_key(MANIFEST_TIME, file_time)
|
|
54
|
+
debug_print("Read manifest", get_key(MANIFEST_FILE))
|
|
55
|
+
|
|
56
|
+
add_chip("default", chip)
|
|
57
|
+
|
|
58
|
+
for history in chip.getkeys('history'):
|
|
59
|
+
history_chip = Chip(design='')
|
|
60
|
+
history_chip.schema.cfg = chip.getdict('history', history)
|
|
61
|
+
history_chip.set('design', chip.design)
|
|
62
|
+
add_chip(history, history_chip)
|
|
63
|
+
|
|
64
|
+
return True
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def init():
|
|
69
|
+
_add_default(DISPLAY_FLOWGRAPH, True)
|
|
70
|
+
_add_default(SELECTED_JOB, None)
|
|
71
|
+
_add_default(SELECTED_NODE, None)
|
|
72
|
+
_add_default(SELECTED_FLOWGRAPH_NODE, None)
|
|
73
|
+
_add_default(SELECTED_SELECTOR_NODE, None)
|
|
74
|
+
_add_default(NODE_SOURCE, None)
|
|
75
|
+
_add_default(SELECTED_FILE, None)
|
|
76
|
+
_add_default(LOADED_CHIPS, {})
|
|
77
|
+
_add_default(MANIFEST_FILE, None)
|
|
78
|
+
_add_default(MANIFEST_LOCK, None)
|
|
79
|
+
_add_default(MANIFEST_TIME, None)
|
|
80
|
+
_add_default(IS_RUNNING, False)
|
|
81
|
+
_add_default(GRAPH_JOBS, None)
|
|
82
|
+
_add_default(UI_WIDTH, None)
|
|
83
|
+
_add_default(APP_LAYOUT, "vertical_flowgraph")
|
|
84
|
+
_add_default(APP_RERUN, None)
|
|
85
|
+
_add_default(APP_RUNNING_REFRESH, 2 * 1000)
|
|
86
|
+
_add_default(APP_STOPPED_REFRESH, 30 * 1000)
|
|
87
|
+
_add_default(MAX_DICT_ITEMS_TO_SHOW, 100)
|
|
88
|
+
_add_default(MAX_FILE_LINES_TO_SHOW, 100)
|
|
89
|
+
_add_default(SELECT_TAB, None)
|
|
90
|
+
_add_default(TAB_INDEX, 0)
|
|
91
|
+
|
|
92
|
+
parser = argparse.ArgumentParser('dashboard')
|
|
93
|
+
parser.add_argument('cfg', nargs='?')
|
|
94
|
+
args = parser.parse_args()
|
|
95
|
+
|
|
96
|
+
if not args.cfg:
|
|
97
|
+
raise ValueError('configuration not provided')
|
|
98
|
+
|
|
99
|
+
if not get_key(LOADED_CHIPS):
|
|
100
|
+
# First time through
|
|
101
|
+
|
|
102
|
+
with open(args.cfg, 'r') as f:
|
|
103
|
+
config = json.load(f)
|
|
104
|
+
|
|
105
|
+
set_key(MANIFEST_FILE, config["manifest"])
|
|
106
|
+
set_key(MANIFEST_LOCK, fasteners.InterProcessLock(config["lock"]))
|
|
107
|
+
|
|
108
|
+
update_manifest()
|
|
109
|
+
chip = get_chip("default")
|
|
110
|
+
for graph_info in config['graph_chips']:
|
|
111
|
+
file_path = graph_info['path']
|
|
112
|
+
graph_chip = Chip(design='')
|
|
113
|
+
graph_chip.read_manifest(file_path)
|
|
114
|
+
graph_chip.unset('arg', 'step')
|
|
115
|
+
graph_chip.unset('arg', 'index')
|
|
116
|
+
|
|
117
|
+
if graph_info['cwd']:
|
|
118
|
+
graph_chip.cwd = graph_info['cwd']
|
|
119
|
+
|
|
120
|
+
add_chip(os.path.basename(file_path), graph_chip)
|
|
121
|
+
|
|
122
|
+
chip_step = chip.get('arg', 'step')
|
|
123
|
+
chip_index = chip.get('arg', 'index')
|
|
124
|
+
|
|
125
|
+
if chip_step and chip_index:
|
|
126
|
+
set_key(SELECTED_NODE, f'{chip_step}{chip_index}')
|
|
127
|
+
|
|
128
|
+
chip = get_chip("default")
|
|
129
|
+
chip.unset('arg', 'step')
|
|
130
|
+
chip.unset('arg', 'index')
|
|
131
|
+
|
|
132
|
+
if not get_key(SELECTED_JOB):
|
|
133
|
+
set_key(SELECTED_JOB, "default")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def setup():
|
|
137
|
+
with streamlit.empty():
|
|
138
|
+
# get width
|
|
139
|
+
set_key(UI_WIDTH, streamlit_javascript.st_javascript("window.innerWidth"))
|
|
140
|
+
# replace with a empty container to avoid adding a gap at the top
|
|
141
|
+
streamlit.empty()
|
|
142
|
+
|
|
143
|
+
set_key(NODE_SOURCE, None)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_chip(job=None):
|
|
147
|
+
if not job:
|
|
148
|
+
job = get_key(SELECTED_JOB)
|
|
149
|
+
return get_key(LOADED_CHIPS)[job]
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def add_chip(name, chip):
|
|
153
|
+
streamlit.session_state[LOADED_CHIPS][name] = chip
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def get_chips():
|
|
157
|
+
chips = list(get_key(LOADED_CHIPS).keys())
|
|
158
|
+
chips.remove('default')
|
|
159
|
+
chips.insert(0, 'default')
|
|
160
|
+
return chips
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def get_selected_node():
|
|
164
|
+
if get_key(NODE_SOURCE) == "flowgraph":
|
|
165
|
+
return get_key(SELECTED_FLOWGRAPH_NODE)
|
|
166
|
+
|
|
167
|
+
if get_key(NODE_SOURCE) == "selector":
|
|
168
|
+
return get_key(SELECTED_SELECTOR_NODE)
|
|
169
|
+
|
|
170
|
+
return get_key(SELECTED_NODE)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_key(key):
|
|
174
|
+
return streamlit.session_state[key]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def set_key(key, value):
|
|
178
|
+
changed = value != streamlit.session_state[key]
|
|
179
|
+
if changed:
|
|
180
|
+
debug_print("set_key()", key, "changed", streamlit.session_state[key], "->", value)
|
|
181
|
+
streamlit.session_state[key] = value
|
|
182
|
+
return True
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def del_key(key):
|
|
187
|
+
debug_print("del_key()", key)
|
|
188
|
+
if key in streamlit.session_state:
|
|
189
|
+
del streamlit.session_state[key]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def compute_component_size(minimum, requested_px):
|
|
193
|
+
ui_width = get_key(UI_WIDTH)
|
|
194
|
+
|
|
195
|
+
if ui_width > 0:
|
|
196
|
+
return min(requested_px / ui_width, minimum)
|
|
197
|
+
|
|
198
|
+
return minimum
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def debug_print(*args):
|
|
202
|
+
if not _DEBUG:
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
print(*args)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def debug_print_state():
|
|
209
|
+
if not _DEBUG:
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
for n, key in enumerate(sorted(streamlit.session_state.keys())):
|
|
213
|
+
value = streamlit.session_state[key]
|
|
214
|
+
print("state", n, key, type(value), value)
|
|
215
|
+
print()
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from siliconcompiler import NodeStatus
|
|
2
|
+
from siliconcompiler.flowgraph import _get_flowgraph_nodes
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_chip_cwd(chip, manifest):
|
|
8
|
+
build_dir = Path(chip.get('option', 'builddir'))
|
|
9
|
+
|
|
10
|
+
manifest_path = Path(manifest)
|
|
11
|
+
for path in manifest_path.parents:
|
|
12
|
+
if build_dir.name == path.name:
|
|
13
|
+
return str(path.parent)
|
|
14
|
+
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def make_node_to_step_index_map(chip, metric_dataframe):
|
|
19
|
+
'''
|
|
20
|
+
Returns a map from the name of a node to the associated step, index pair.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
metric_dataframe (pandas.DataFrame) : A dataframe full of all metrics and all
|
|
24
|
+
nodes of the selected chip
|
|
25
|
+
'''
|
|
26
|
+
node_to_step_index_map = {}
|
|
27
|
+
for step, index in _get_flowgraph_nodes(chip, chip.get('option', 'flow')):
|
|
28
|
+
node_to_step_index_map[f'{step}{index}'] = (step, index)
|
|
29
|
+
|
|
30
|
+
# concatenate step and index
|
|
31
|
+
metric_dataframe.columns = metric_dataframe.columns.map(lambda x: f'{x[0]}{x[1]}')
|
|
32
|
+
return node_to_step_index_map, metric_dataframe
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def make_metric_to_metric_unit_map(metric_dataframe):
|
|
36
|
+
'''
|
|
37
|
+
Returns a map from the name of a metric to the associated metric and unit in
|
|
38
|
+
the form f'{x[0]} ({x[1]})'
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
metric_dataframe (pandas.DataFrame) : A dataframe full of all metrics and all
|
|
42
|
+
nodes of the selected chip.
|
|
43
|
+
'''
|
|
44
|
+
metric_to_metric_unit_map = {}
|
|
45
|
+
for metric, unit in metric_dataframe.index.tolist():
|
|
46
|
+
if unit != '':
|
|
47
|
+
metric_to_metric_unit_map[f'{metric} ({unit})'] = metric
|
|
48
|
+
else:
|
|
49
|
+
metric_to_metric_unit_map[metric] = metric
|
|
50
|
+
# concatenate metric and unit
|
|
51
|
+
metric_dataframe.index = metric_dataframe.index.map(lambda x: f'{x[0]} ({x[1]})'
|
|
52
|
+
if x[1] else x[0])
|
|
53
|
+
return metric_to_metric_unit_map, metric_dataframe
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_running(chip):
|
|
57
|
+
for step, index in _get_flowgraph_nodes(chip, chip.get('option', 'flow')):
|
|
58
|
+
state = chip.get('record', 'status', step=step, index=index)
|
|
59
|
+
if not NodeStatus.is_done(state):
|
|
60
|
+
return True
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def generate_metric_dataframe(chip):
|
|
65
|
+
from siliconcompiler.report import report
|
|
66
|
+
|
|
67
|
+
metric_dataframe = report.make_metric_dataframe(chip)
|
|
68
|
+
node_to_step_index_map, metric_dataframe = \
|
|
69
|
+
make_node_to_step_index_map(chip, metric_dataframe)
|
|
70
|
+
metric_to_metric_unit_map, metric_dataframe = \
|
|
71
|
+
make_metric_to_metric_unit_map(metric_dataframe)
|
|
72
|
+
|
|
73
|
+
return metric_dataframe, node_to_step_index_map, metric_to_metric_unit_map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import gzip
|
|
2
|
+
import os
|
|
3
|
+
from siliconcompiler import utils, sc_open
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def is_file_is_binary(path, compressed):
|
|
7
|
+
# Read first chunk and check for non characters
|
|
8
|
+
try:
|
|
9
|
+
if compressed:
|
|
10
|
+
with gzip.open(path, 'rt') as f:
|
|
11
|
+
f.read(8196)
|
|
12
|
+
else:
|
|
13
|
+
with open(path, "r") as f:
|
|
14
|
+
f.read(8196)
|
|
15
|
+
except UnicodeDecodeError:
|
|
16
|
+
return True
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def read_file(path, max_lines):
|
|
21
|
+
_, compressed_file_extension = os.path.splitext(path.lower())
|
|
22
|
+
file_info = []
|
|
23
|
+
honor_max_file = max_lines is not None
|
|
24
|
+
|
|
25
|
+
def read_file(fid):
|
|
26
|
+
for line in fid:
|
|
27
|
+
file_info.append(line.rstrip())
|
|
28
|
+
if honor_max_file and len(file_info) >= max_lines:
|
|
29
|
+
file_info.append('... truncated ...')
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
is_compressed = compressed_file_extension == '.gz'
|
|
33
|
+
if is_file_is_binary(path, is_compressed):
|
|
34
|
+
return "Binary file"
|
|
35
|
+
|
|
36
|
+
if is_compressed:
|
|
37
|
+
with gzip.open(path, 'rt') as fid:
|
|
38
|
+
read_file(fid)
|
|
39
|
+
else:
|
|
40
|
+
with sc_open(path) as fid:
|
|
41
|
+
read_file(fid)
|
|
42
|
+
return "\n".join(file_info)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_file_type(ext):
|
|
46
|
+
if ext in ("v", "vh", "sv", "svh", "vg"):
|
|
47
|
+
return "verilog"
|
|
48
|
+
if ext in ("vhdl", "vhd"):
|
|
49
|
+
return "vhdl"
|
|
50
|
+
if ext in ("tcl", "sdc", "xdc"):
|
|
51
|
+
return "tcl"
|
|
52
|
+
if ext in ("c", "cpp", "cc", "h"):
|
|
53
|
+
return "cpp"
|
|
54
|
+
if ext in ("csv",):
|
|
55
|
+
return "csv"
|
|
56
|
+
if ext in ("md",):
|
|
57
|
+
return "markdown"
|
|
58
|
+
if ext in ("sh",):
|
|
59
|
+
return "bash"
|
|
60
|
+
return "log"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_file_icon(file):
|
|
64
|
+
if not file:
|
|
65
|
+
return 'file'
|
|
66
|
+
ext = utils.get_file_ext(file)
|
|
67
|
+
file_type = get_file_type(ext)
|
|
68
|
+
if file.endswith('.pkg.json'):
|
|
69
|
+
return 'boxes'
|
|
70
|
+
elif ext in ('png', 'jpg', 'jpeg'):
|
|
71
|
+
return 'file-image'
|
|
72
|
+
elif ext == 'json':
|
|
73
|
+
return 'file-json'
|
|
74
|
+
elif file_type in ('verilog', 'tcl', 'vhdl', 'cpp', 'bash'):
|
|
75
|
+
return 'file-code'
|
|
76
|
+
elif ext in ('log', 'rpt', 'drc', 'warnings', 'errors'):
|
|
77
|
+
return 'file-text'
|
|
78
|
+
return 'file'
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def convert_filepaths_to_select_tree(logs_and_reports):
|
|
82
|
+
"""
|
|
83
|
+
Converts the logs_and_reports found to the structure
|
|
84
|
+
required by streamlit_tree_select. Success is predicated on the order of
|
|
85
|
+
logs_and_reports outlined in report.get_files.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
logs_and_reports (list) : A list of 3-tuples with order of a path name,
|
|
89
|
+
folder in the..., and files in the....
|
|
90
|
+
"""
|
|
91
|
+
if not logs_and_reports:
|
|
92
|
+
return []
|
|
93
|
+
|
|
94
|
+
all_files = {}
|
|
95
|
+
for path_name, folders, files in logs_and_reports:
|
|
96
|
+
all_files[path_name] = {
|
|
97
|
+
'files': list(files),
|
|
98
|
+
'folders': list(folders)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def organize_node(base_folder):
|
|
102
|
+
nodes = []
|
|
103
|
+
|
|
104
|
+
for folder in all_files[base_folder]['folders']:
|
|
105
|
+
path = os.path.join(base_folder, folder)
|
|
106
|
+
nodes.append({
|
|
107
|
+
'value': path,
|
|
108
|
+
'label': folder,
|
|
109
|
+
'children': organize_node(path)
|
|
110
|
+
})
|
|
111
|
+
for file in all_files[base_folder]['files']:
|
|
112
|
+
nodes.append({
|
|
113
|
+
'value': os.path.join(base_folder, file),
|
|
114
|
+
'label': file
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return nodes
|
|
118
|
+
|
|
119
|
+
starting_path_name = logs_and_reports[0][0]
|
|
120
|
+
return organize_node(starting_path_name)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import streamlit
|
|
2
|
+
|
|
3
|
+
from siliconcompiler.report.dashboard import components
|
|
4
|
+
from siliconcompiler.report.dashboard import layouts
|
|
5
|
+
from siliconcompiler.report.dashboard import state
|
|
6
|
+
from siliconcompiler.report.dashboard import utils
|
|
7
|
+
|
|
8
|
+
import streamlit_autorefresh
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
# opened by running command in siliconcompiler/apps/sc_dashboard.py
|
|
13
|
+
state.init()
|
|
14
|
+
|
|
15
|
+
components.setup_page()
|
|
16
|
+
state.setup()
|
|
17
|
+
|
|
18
|
+
layout = layouts.get_layout(state.get_key(state.APP_LAYOUT))
|
|
19
|
+
layout()
|
|
20
|
+
|
|
21
|
+
reload = False
|
|
22
|
+
if state.get_key(state.SELECTED_JOB) == 'default':
|
|
23
|
+
reload = state.set_key(state.IS_RUNNING, utils.is_running(state.get_chip()))
|
|
24
|
+
|
|
25
|
+
if state.get_key(state.IS_RUNNING):
|
|
26
|
+
update_interval = state.get_key(state.APP_RUNNING_REFRESH)
|
|
27
|
+
else:
|
|
28
|
+
update_interval = state.get_key(state.APP_STOPPED_REFRESH)
|
|
29
|
+
|
|
30
|
+
streamlit_autorefresh.st_autorefresh(interval=update_interval)
|
|
31
|
+
|
|
32
|
+
state.debug_print_state()
|
|
33
|
+
|
|
34
|
+
if reload or state.update_manifest() or state.get_key(state.APP_RERUN):
|
|
35
|
+
state.set_key(state.APP_RERUN, None)
|
|
36
|
+
streamlit.rerun()
|
siliconcompiler/report/report.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fnmatch
|
|
1
2
|
import pandas
|
|
2
3
|
import os
|
|
3
4
|
from siliconcompiler import Schema
|
|
@@ -104,7 +105,8 @@ def make_manifest_helper(manifest_subsect, modified_manifest_subsect):
|
|
|
104
105
|
|
|
105
106
|
def build_leaf(manifest_subsect):
|
|
106
107
|
if manifest_subsect['pernode'] == 'never':
|
|
107
|
-
if Schema.GLOBAL_KEY in manifest_subsect['node']
|
|
108
|
+
if Schema.GLOBAL_KEY in manifest_subsect['node'] and \
|
|
109
|
+
Schema.GLOBAL_KEY in manifest_subsect['node'][Schema.GLOBAL_KEY]:
|
|
108
110
|
value = manifest_subsect['node'][Schema.GLOBAL_KEY][Schema.GLOBAL_KEY]['value']
|
|
109
111
|
else:
|
|
110
112
|
value = manifest_subsect['node']['default']['default']['value']
|
|
@@ -201,7 +203,7 @@ def search_manifest_keys(manifest, key):
|
|
|
201
203
|
'''
|
|
202
204
|
filtered_manifest = {}
|
|
203
205
|
for dict_key in manifest:
|
|
204
|
-
if key
|
|
206
|
+
if fnmatch.fnmatch(dict_key, key):
|
|
205
207
|
filtered_manifest[dict_key] = manifest[dict_key]
|
|
206
208
|
elif isinstance(manifest[dict_key], dict):
|
|
207
209
|
result = search_manifest_keys(manifest[dict_key], key)
|
|
@@ -225,8 +227,16 @@ def search_manifest_values(manifest, value):
|
|
|
225
227
|
result = search_manifest_values(manifest[key], value)
|
|
226
228
|
if result: # result is non-empty
|
|
227
229
|
filtered_manifest[key] = result
|
|
228
|
-
|
|
229
|
-
|
|
230
|
+
else:
|
|
231
|
+
if manifest[key] is None:
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
if isinstance(manifest[key], (list, tuple)):
|
|
235
|
+
if fnmatch.filter([str(v) for v in manifest[key]], value):
|
|
236
|
+
filtered_manifest[key] = manifest[key]
|
|
237
|
+
else:
|
|
238
|
+
if fnmatch.fnmatch(str(manifest[key]), value):
|
|
239
|
+
filtered_manifest[key] = manifest[key]
|
|
230
240
|
return filtered_manifest
|
|
231
241
|
|
|
232
242
|
|
|
@@ -251,8 +261,12 @@ def search_manifest(manifest, key_search=None, value_search=None):
|
|
|
251
261
|
'''
|
|
252
262
|
return_manifest = manifest
|
|
253
263
|
if key_search:
|
|
264
|
+
if '*' not in key_search or '?' not in key_search:
|
|
265
|
+
key_search = f'*{key_search}*'
|
|
254
266
|
return_manifest = search_manifest_keys(return_manifest, key_search)
|
|
255
267
|
if value_search:
|
|
268
|
+
if '*' not in value_search or '?' not in value_search:
|
|
269
|
+
value_search = f'*{value_search}*'
|
|
256
270
|
return_manifest = search_manifest_values(return_manifest, value_search)
|
|
257
271
|
return return_manifest
|
|
258
272
|
|
|
@@ -286,7 +300,11 @@ def get_metrics_source(chip, step, index):
|
|
|
286
300
|
'''
|
|
287
301
|
file_to_metric = {}
|
|
288
302
|
tool, task = get_tool_task(chip, step, index)
|
|
303
|
+
if not chip.valid('tool', tool, 'task', task, 'report'):
|
|
304
|
+
return file_to_metric
|
|
305
|
+
|
|
289
306
|
metrics = chip.getkeys('tool', tool, 'task', task, 'report')
|
|
307
|
+
|
|
290
308
|
for metric in metrics:
|
|
291
309
|
sources = chip.get('tool', tool, 'task', task, 'report', metric, step=step, index=index)
|
|
292
310
|
for source in sources:
|
|
@@ -134,6 +134,10 @@ def _finalize_run(chip, environment):
|
|
|
134
134
|
filepath = os.path.join(chip.getworkdir(), f"{chip.design}.pkg.json")
|
|
135
135
|
chip.write_manifest(filepath)
|
|
136
136
|
|
|
137
|
+
# Update dashboard
|
|
138
|
+
if chip._dash:
|
|
139
|
+
chip._dash.update_manifest()
|
|
140
|
+
|
|
137
141
|
send_messages.send(chip, 'summary', None, None)
|
|
138
142
|
|
|
139
143
|
|
|
@@ -278,6 +282,11 @@ def _local_process(chip, flow):
|
|
|
278
282
|
processes = {}
|
|
279
283
|
local_processes = []
|
|
280
284
|
_prepare_nodes(chip, nodes_to_run, processes, local_processes, flow)
|
|
285
|
+
|
|
286
|
+
# Update dashboard before run begins
|
|
287
|
+
if chip._dash:
|
|
288
|
+
chip._dash.update_manifest()
|
|
289
|
+
|
|
281
290
|
try:
|
|
282
291
|
_launch_nodes(chip, nodes_to_run, processes, local_processes)
|
|
283
292
|
except KeyboardInterrupt:
|
|
@@ -985,6 +994,8 @@ def _check_logfile(chip, step, index, quiet=False, run_func=None):
|
|
|
985
994
|
Check log file (must be after post-process)
|
|
986
995
|
'''
|
|
987
996
|
if run_func is None:
|
|
997
|
+
tool, task = get_tool_task(chip, step, index)
|
|
998
|
+
|
|
988
999
|
log_file = os.path.join(chip.getworkdir(step=step, index=index), f'{step}.log')
|
|
989
1000
|
matches = check_logfile(chip, step=step, index=index,
|
|
990
1001
|
display=not quiet,
|
|
@@ -994,13 +1005,27 @@ def _check_logfile(chip, step, index, quiet=False, run_func=None):
|
|
|
994
1005
|
if errors is None:
|
|
995
1006
|
errors = 0
|
|
996
1007
|
errors += matches['errors']
|
|
997
|
-
|
|
1008
|
+
|
|
1009
|
+
sources = [f'{step}.log']
|
|
1010
|
+
if chip.valid('tool', tool, 'task', task, 'regex', 'errors'):
|
|
1011
|
+
if chip.get('tool', tool, 'task', task, 'regex', 'errors',
|
|
1012
|
+
step=step, index=index):
|
|
1013
|
+
sources.append(f'{step}.errors')
|
|
1014
|
+
|
|
1015
|
+
record_metric(chip, step, index, 'errors', errors, sources)
|
|
998
1016
|
if 'warnings' in matches:
|
|
999
1017
|
warnings = chip.get('metric', 'warnings', step=step, index=index)
|
|
1000
1018
|
if warnings is None:
|
|
1001
1019
|
warnings = 0
|
|
1002
1020
|
warnings += matches['warnings']
|
|
1003
|
-
|
|
1021
|
+
|
|
1022
|
+
sources = [f'{step}.log']
|
|
1023
|
+
if chip.valid('tool', tool, 'task', task, 'regex', 'warnings'):
|
|
1024
|
+
if chip.get('tool', tool, 'task', task, 'regex', 'warnings',
|
|
1025
|
+
step=step, index=index):
|
|
1026
|
+
sources.append(f'{step}.warnings')
|
|
1027
|
+
|
|
1028
|
+
record_metric(chip, step, index, 'warnings', warnings, sources)
|
|
1004
1029
|
|
|
1005
1030
|
|
|
1006
1031
|
def _executenode(chip, step, index, replay):
|
|
@@ -1354,16 +1379,16 @@ def _prepare_nodes(chip, nodes_to_run, processes, local_processes, flow):
|
|
|
1354
1379
|
def _check_node_dependencies(chip, node, deps, deps_was_successful):
|
|
1355
1380
|
had_deps = len(deps) > 0
|
|
1356
1381
|
step, index = node
|
|
1357
|
-
tool,
|
|
1382
|
+
tool, _ = get_tool_task(chip, step, index)
|
|
1358
1383
|
|
|
1359
1384
|
# Clear any nodes that have finished from dependency list.
|
|
1360
1385
|
for in_step, in_index in list(deps):
|
|
1361
1386
|
in_status = chip.get('record', 'status', step=in_step, index=in_index)
|
|
1362
|
-
if
|
|
1387
|
+
if NodeStatus.is_done(in_status):
|
|
1363
1388
|
deps.remove((in_step, in_index))
|
|
1364
1389
|
if in_status == NodeStatus.SUCCESS:
|
|
1365
1390
|
deps_was_successful[node] = True
|
|
1366
|
-
if
|
|
1391
|
+
if NodeStatus.is_error(in_status):
|
|
1367
1392
|
# Fail if any dependency failed for non-builtin task
|
|
1368
1393
|
if tool != 'builtin':
|
|
1369
1394
|
deps.clear()
|
|
@@ -1418,7 +1443,7 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1418
1443
|
_get_callback('pre_run')(chip)
|
|
1419
1444
|
|
|
1420
1445
|
while len(nodes_to_run) > 0 or len(running_nodes) > 0:
|
|
1421
|
-
_process_completed_nodes(chip, processes, running_nodes)
|
|
1446
|
+
changed = _process_completed_nodes(chip, processes, running_nodes)
|
|
1422
1447
|
|
|
1423
1448
|
# Check for new nodes that can be launched.
|
|
1424
1449
|
for node, deps in list(nodes_to_run.items()):
|
|
@@ -1440,6 +1465,9 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1440
1465
|
if _get_callback('pre_node'):
|
|
1441
1466
|
_get_callback('pre_node')(chip, *node)
|
|
1442
1467
|
|
|
1468
|
+
chip.set('record', 'status', NodeStatus.RUNNING, step=node[0], index=node[1])
|
|
1469
|
+
changed = True
|
|
1470
|
+
|
|
1443
1471
|
processes[node].start()
|
|
1444
1472
|
del nodes_to_run[node]
|
|
1445
1473
|
running_nodes[node] = requested_threads
|
|
@@ -1452,11 +1480,16 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1452
1480
|
raise SiliconCompilerError(
|
|
1453
1481
|
'Nodes left to run, but no running nodes. From/to may be invalid.', chip=chip)
|
|
1454
1482
|
|
|
1483
|
+
if chip._dash and changed:
|
|
1484
|
+
# Update dashboard if the manifest changed
|
|
1485
|
+
chip._dash.update_manifest()
|
|
1486
|
+
|
|
1455
1487
|
# TODO: exponential back-off with max?
|
|
1456
1488
|
time.sleep(0.1)
|
|
1457
1489
|
|
|
1458
1490
|
|
|
1459
1491
|
def _process_completed_nodes(chip, processes, running_nodes):
|
|
1492
|
+
changed = False
|
|
1460
1493
|
for node in list(running_nodes.keys()):
|
|
1461
1494
|
if not processes[node].is_alive():
|
|
1462
1495
|
step, index = node
|
|
@@ -1477,9 +1510,13 @@ def _process_completed_nodes(chip, processes, running_nodes):
|
|
|
1477
1510
|
|
|
1478
1511
|
chip.set('record', 'status', status, step=step, index=index)
|
|
1479
1512
|
|
|
1513
|
+
changed = True
|
|
1514
|
+
|
|
1480
1515
|
if _get_callback('post_node'):
|
|
1481
1516
|
_get_callback('post_node')(chip, *node)
|
|
1482
1517
|
|
|
1518
|
+
return changed
|
|
1519
|
+
|
|
1483
1520
|
|
|
1484
1521
|
def _check_nodes_status(chip, flow):
|
|
1485
1522
|
def success(node):
|
|
@@ -628,7 +628,7 @@ class Schema:
|
|
|
628
628
|
return copy.deepcopy(cfg)
|
|
629
629
|
|
|
630
630
|
###########################################################################
|
|
631
|
-
def valid(self, *args, default_valid=False, job=None):
|
|
631
|
+
def valid(self, *args, default_valid=False, job=None, check_complete=False):
|
|
632
632
|
"""
|
|
633
633
|
Checks validity of a keypath.
|
|
634
634
|
|
|
@@ -653,7 +653,9 @@ class Schema:
|
|
|
653
653
|
cfg = cfg[default]
|
|
654
654
|
else:
|
|
655
655
|
return False
|
|
656
|
-
|
|
656
|
+
if check_complete:
|
|
657
|
+
return Schema._is_leaf(cfg)
|
|
658
|
+
return True
|
|
657
659
|
|
|
658
660
|
##########################################################################
|
|
659
661
|
def has_field(self, *args):
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
proc sc_collect_pin_constraints {
|
|
2
|
-
placement_pins_arg
|
|
3
|
-
ordered_pins_arg
|
|
4
|
-
sc_side_layer_func
|
|
5
|
-
{ print_func puts }
|
|
1
|
+
proc sc_collect_pin_constraints {
|
|
2
|
+
placement_pins_arg
|
|
3
|
+
ordered_pins_arg
|
|
4
|
+
sc_side_layer_func
|
|
5
|
+
{ print_func puts }
|
|
6
|
+
} {
|
|
6
7
|
upvar 1 $placement_pins_arg placement_pins
|
|
7
8
|
upvar 1 $ordered_pins_arg ordered_pins
|
|
8
9
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from siliconcompiler.tools._common import input_provides, add_common_file, get_tool_task
|
|
2
|
+
from siliconcompiler.tools._common.asic import set_tool_task_var
|
|
2
3
|
from siliconcompiler.tools.openroad.openroad import setup as setup_tool
|
|
3
4
|
from siliconcompiler.tools.openroad.openroad import build_pex_corners
|
|
4
5
|
from siliconcompiler.tools.openroad.openroad import post_process as or_post_process
|
|
@@ -46,6 +47,10 @@ def setup(chip):
|
|
|
46
47
|
'script to insert the padring',
|
|
47
48
|
field='help')
|
|
48
49
|
|
|
50
|
+
set_tool_task_var(chip, param_key='remove_synth_buffers',
|
|
51
|
+
default_value=True,
|
|
52
|
+
schelp='remove buffers inserted by synthesis')
|
|
53
|
+
|
|
49
54
|
snap = chip.get('tool', tool, 'task', task, 'var', 'ifp_snap_strategy',
|
|
50
55
|
step=step, index=index)[0]
|
|
51
56
|
snaps_allowed = ('none', 'site', 'manufacturing_grid')
|