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
siliconcompiler/_common.py
CHANGED
|
@@ -33,6 +33,18 @@ class NodeStatus():
|
|
|
33
33
|
NodeStatus.PENDING,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
+
def is_success(status):
|
|
37
|
+
return status in (
|
|
38
|
+
NodeStatus.SUCCESS,
|
|
39
|
+
NodeStatus.SKIPPED
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def is_error(status):
|
|
43
|
+
return status in (
|
|
44
|
+
NodeStatus.ERROR,
|
|
45
|
+
NodeStatus.TIMEOUT
|
|
46
|
+
)
|
|
47
|
+
|
|
36
48
|
|
|
37
49
|
###############################################################################
|
|
38
50
|
# Package Customization classes
|
siliconcompiler/_metadata.py
CHANGED
|
@@ -82,7 +82,11 @@ To include another chip object to compare to:
|
|
|
82
82
|
raise ValueError(f'not a valid file path : {file_path}')
|
|
83
83
|
graph_chip = siliconcompiler.core.Chip(design='')
|
|
84
84
|
graph_chip.read_manifest(file_path)
|
|
85
|
-
graph_chips.append({
|
|
85
|
+
graph_chips.append({
|
|
86
|
+
'chip': graph_chip,
|
|
87
|
+
'name': name,
|
|
88
|
+
'cfg_path': os.path.abspath(file_path)
|
|
89
|
+
})
|
|
86
90
|
|
|
87
91
|
chip._dashboard(wait=True, port=switches['port'], graph_chips=graph_chips)
|
|
88
92
|
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Copyright 2024 Silicon Compiler Authors. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import glob
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import shutil
|
|
8
|
+
import re
|
|
9
|
+
import os.path
|
|
10
|
+
from collections.abc import Container
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import siliconcompiler
|
|
13
|
+
from siliconcompiler.scheduler import _get_machine_info
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChoiceOptional(Container):
|
|
17
|
+
def __init__(self, choices):
|
|
18
|
+
super().__init__()
|
|
19
|
+
|
|
20
|
+
self.__choices = set(choices)
|
|
21
|
+
|
|
22
|
+
def __contains__(self, item):
|
|
23
|
+
if not item:
|
|
24
|
+
# allow empty value
|
|
25
|
+
return True
|
|
26
|
+
return item in self.__choices
|
|
27
|
+
|
|
28
|
+
def __iter__(self):
|
|
29
|
+
return self.__choices.__iter__()
|
|
30
|
+
|
|
31
|
+
def get_items(self, choices):
|
|
32
|
+
items = set(choices)
|
|
33
|
+
return sorted(list(items))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def install_tool(tool, script, build_dir, prefix):
|
|
37
|
+
# Ensure build dir is available
|
|
38
|
+
build_dir = Path(build_dir) / tool
|
|
39
|
+
shutil.rmtree(str(build_dir), ignore_errors=True)
|
|
40
|
+
build_dir.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
|
|
42
|
+
# setup environment
|
|
43
|
+
env = os.environ.copy()
|
|
44
|
+
env["PREFIX"] = prefix
|
|
45
|
+
|
|
46
|
+
# run
|
|
47
|
+
ret = subprocess.call(script, env=env, cwd=build_dir)
|
|
48
|
+
if ret != 0:
|
|
49
|
+
print(f"Error occurred while building/installing {tool}")
|
|
50
|
+
return False
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def show_tool(tool, script):
|
|
55
|
+
def print_header(head):
|
|
56
|
+
border_len = max(80, len(script) + 2)
|
|
57
|
+
border = border_len*"#"
|
|
58
|
+
print(border)
|
|
59
|
+
print(f"# {tool} script / {head}")
|
|
60
|
+
if head == "start":
|
|
61
|
+
print(f"# {script}")
|
|
62
|
+
print(border)
|
|
63
|
+
|
|
64
|
+
print_header("start")
|
|
65
|
+
|
|
66
|
+
with open(script) as f:
|
|
67
|
+
for line in f:
|
|
68
|
+
print(line.rstrip())
|
|
69
|
+
|
|
70
|
+
print_header("end")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _get_os_name():
|
|
74
|
+
machine_info = _get_machine_info()
|
|
75
|
+
system = machine_info.get('system', "").lower()
|
|
76
|
+
distro = machine_info.get('distro', "").lower()
|
|
77
|
+
osversion = machine_info.get('osversion', "").lower()
|
|
78
|
+
if system == 'linux':
|
|
79
|
+
if distro == 'ubuntu':
|
|
80
|
+
version, _ = osversion.split('.')
|
|
81
|
+
return f"{distro}{version}"
|
|
82
|
+
elif distro == 'rocky':
|
|
83
|
+
version, _ = osversion.split('.')
|
|
84
|
+
return f"rhel{version}"
|
|
85
|
+
elif distro == 'rhel':
|
|
86
|
+
version, _ = osversion.split('.')
|
|
87
|
+
return f"rhel{version}"
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def print_machine_info():
|
|
92
|
+
machine_info = _get_machine_info()
|
|
93
|
+
mapped_os = _get_os_name()
|
|
94
|
+
|
|
95
|
+
print("System: ", machine_info.get('system', None))
|
|
96
|
+
print("Distro: ", machine_info.get('distro', None))
|
|
97
|
+
print("Version: ", machine_info.get('osversion', None))
|
|
98
|
+
print("Mapped OS:", mapped_os)
|
|
99
|
+
print("Scripts: ", _get_tool_script_dir())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _get_tool_script_dir():
|
|
103
|
+
return Path(siliconcompiler.__file__).parent / "toolscripts"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _get_tools_list():
|
|
107
|
+
tools_root = _get_tool_script_dir()
|
|
108
|
+
|
|
109
|
+
script_dir = None
|
|
110
|
+
os_dir = _get_os_name()
|
|
111
|
+
if os_dir:
|
|
112
|
+
script_dir = tools_root / os_dir
|
|
113
|
+
if not script_dir.exists():
|
|
114
|
+
script_dir = None
|
|
115
|
+
|
|
116
|
+
tools = {}
|
|
117
|
+
if script_dir:
|
|
118
|
+
for script in glob.glob(str(script_dir / "install-*.sh")):
|
|
119
|
+
tool = re.match(r"install-(.*)\.sh", os.path.basename(script).lower())
|
|
120
|
+
tools[tool.group(1)] = script
|
|
121
|
+
|
|
122
|
+
return tools
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _recommended_tool_groups(tools):
|
|
126
|
+
groups = {
|
|
127
|
+
"asic": {"surelog", "sv2v", "yosys", "openroad", "klayout"},
|
|
128
|
+
"fpga": {"surelog", "sv2v", "yosys", "vpr"},
|
|
129
|
+
"digital-simulation": {"verilator", "icarus"},
|
|
130
|
+
"analog-simulation": {"xyce"}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
filter_groups = {}
|
|
134
|
+
for group, group_tools in groups.items():
|
|
135
|
+
if all([tool in tools for tool in group_tools]):
|
|
136
|
+
filter_groups[group] = group_tools
|
|
137
|
+
return filter_groups
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main():
|
|
141
|
+
progname = "sc-install"
|
|
142
|
+
description = """
|
|
143
|
+
-----------------------------------------------------------
|
|
144
|
+
SC app install supported tools.
|
|
145
|
+
|
|
146
|
+
To install a single tool:
|
|
147
|
+
sc-install openroad
|
|
148
|
+
|
|
149
|
+
To install multiple tools:
|
|
150
|
+
sc-install openroad yosys klayout
|
|
151
|
+
|
|
152
|
+
To install a group of tools:
|
|
153
|
+
sc-install -group asic
|
|
154
|
+
|
|
155
|
+
To install tools in a different location:
|
|
156
|
+
sc-install -prefix /usr/local yosys
|
|
157
|
+
|
|
158
|
+
To build tools in a different location:
|
|
159
|
+
sc-install -build_dir /tmp yosys
|
|
160
|
+
|
|
161
|
+
To show the install script:
|
|
162
|
+
sc-install -show openroad
|
|
163
|
+
|
|
164
|
+
To system debugging information (this should only be used to debug):
|
|
165
|
+
sc-install -debug_machine
|
|
166
|
+
-----------------------------------------------------------
|
|
167
|
+
"""
|
|
168
|
+
parser = argparse.ArgumentParser(
|
|
169
|
+
prog=progname,
|
|
170
|
+
description=description,
|
|
171
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
172
|
+
|
|
173
|
+
tools = _get_tools_list()
|
|
174
|
+
|
|
175
|
+
tool_choices = ChoiceOptional(tools.keys())
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"tool",
|
|
178
|
+
nargs="*",
|
|
179
|
+
choices=tool_choices,
|
|
180
|
+
help="tool to install")
|
|
181
|
+
|
|
182
|
+
tool_groups = _recommended_tool_groups(tools)
|
|
183
|
+
parser.add_argument(
|
|
184
|
+
"-group",
|
|
185
|
+
nargs="+",
|
|
186
|
+
choices=tool_groups.keys(),
|
|
187
|
+
help=f"tool group to install{' - not supported' if not tool_groups else ''}")
|
|
188
|
+
|
|
189
|
+
parser.add_argument(
|
|
190
|
+
"-prefix",
|
|
191
|
+
default=Path.home() / ".local",
|
|
192
|
+
help="Prefix to use when installing tool",
|
|
193
|
+
metavar="<path>")
|
|
194
|
+
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
"-build_dir",
|
|
197
|
+
default=Path.home() / ".sc" / "tool_build",
|
|
198
|
+
help="Directory to build the tool in",
|
|
199
|
+
metavar="<path>")
|
|
200
|
+
|
|
201
|
+
parser.add_argument(
|
|
202
|
+
"-show",
|
|
203
|
+
action="store_true",
|
|
204
|
+
help="Show the install script and exit")
|
|
205
|
+
|
|
206
|
+
parser.add_argument(
|
|
207
|
+
"-debug_machine",
|
|
208
|
+
action="store_true",
|
|
209
|
+
help="Show information about this machine and exit")
|
|
210
|
+
|
|
211
|
+
args = parser.parse_args()
|
|
212
|
+
|
|
213
|
+
if args.debug_machine:
|
|
214
|
+
print_machine_info()
|
|
215
|
+
return 0
|
|
216
|
+
|
|
217
|
+
if not args.tool:
|
|
218
|
+
args.tool = []
|
|
219
|
+
|
|
220
|
+
args.tool = list(args.tool)
|
|
221
|
+
if args.group:
|
|
222
|
+
for group in args.group:
|
|
223
|
+
args.tool.extend(tool_groups[group])
|
|
224
|
+
|
|
225
|
+
tools_handled = set()
|
|
226
|
+
for tool in args.tool:
|
|
227
|
+
if tool in tools_handled:
|
|
228
|
+
continue
|
|
229
|
+
tools_handled.add(tool)
|
|
230
|
+
if args.show:
|
|
231
|
+
show_tool(tool, tools[tool])
|
|
232
|
+
else:
|
|
233
|
+
if not install_tool(tool, tools[tool], args.build_dir, args.prefix):
|
|
234
|
+
return 1
|
|
235
|
+
|
|
236
|
+
return 0
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if __name__ == "__main__":
|
|
240
|
+
sys.exit(main())
|
|
@@ -185,7 +185,7 @@ To delete a job, use:
|
|
|
185
185
|
# If only a manifest is specified, make a 'check_progress/' request and report results:
|
|
186
186
|
elif chip_cfg:
|
|
187
187
|
try:
|
|
188
|
-
check_progress(chip)
|
|
188
|
+
check_progress(chip, [], {})
|
|
189
189
|
except SiliconCompilerError as e:
|
|
190
190
|
chip.logger.error(f'{e}')
|
|
191
191
|
return 1
|
siliconcompiler/core.py
CHANGED
|
@@ -88,6 +88,9 @@ class Chip:
|
|
|
88
88
|
# Cache of file hashes
|
|
89
89
|
self.__hashes = {}
|
|
90
90
|
|
|
91
|
+
# Dashboard
|
|
92
|
+
self._dash = None
|
|
93
|
+
|
|
91
94
|
# Showtools
|
|
92
95
|
self._showtools = {}
|
|
93
96
|
for plugin in utils.get_plugins('show'):
|
|
@@ -758,7 +761,7 @@ class Chip:
|
|
|
758
761
|
return fullstr
|
|
759
762
|
|
|
760
763
|
###########################################################################
|
|
761
|
-
def valid(self, *keypath, default_valid=False, job=None):
|
|
764
|
+
def valid(self, *keypath, default_valid=False, job=None, check_complete=False):
|
|
762
765
|
"""
|
|
763
766
|
Checks validity of a keypath.
|
|
764
767
|
|
|
@@ -770,6 +773,7 @@ class Chip:
|
|
|
770
773
|
keypaths as a wildcard. Defaults to False.
|
|
771
774
|
job (str): Jobname to use for dictionary access in place of the
|
|
772
775
|
current active jobname.
|
|
776
|
+
check_complete (bool): Require the keypath be a complete path.
|
|
773
777
|
|
|
774
778
|
Returns:
|
|
775
779
|
Boolean indicating validity of keypath.
|
|
@@ -782,7 +786,10 @@ class Chip:
|
|
|
782
786
|
>>> check = chip.valid('metric', 'foo', '0', 'tasktime', default_valid=True)
|
|
783
787
|
Returns True, even if "foo" and "0" aren't in current configuration.
|
|
784
788
|
"""
|
|
785
|
-
return self.schema.valid(*keypath,
|
|
789
|
+
return self.schema.valid(*keypath,
|
|
790
|
+
default_valid=default_valid,
|
|
791
|
+
job=job,
|
|
792
|
+
check_complete=check_complete)
|
|
786
793
|
|
|
787
794
|
###########################################################################
|
|
788
795
|
def get(self, *keypath, field='value', job=None, step=None, index=None):
|
|
@@ -1108,6 +1115,24 @@ class Chip:
|
|
|
1108
1115
|
Performs a lookup in the io map for the fileset and filetype
|
|
1109
1116
|
and will use those if they are not provided in the arguments
|
|
1110
1117
|
'''
|
|
1118
|
+
# Handle list inputs
|
|
1119
|
+
if isinstance(filename, (list, tuple)):
|
|
1120
|
+
for file in filename:
|
|
1121
|
+
self._add_input_output(
|
|
1122
|
+
category,
|
|
1123
|
+
file,
|
|
1124
|
+
fileset=fileset,
|
|
1125
|
+
filetype=filetype,
|
|
1126
|
+
iomap=iomap,
|
|
1127
|
+
step=step,
|
|
1128
|
+
index=index,
|
|
1129
|
+
package=package,
|
|
1130
|
+
quiet=quiet)
|
|
1131
|
+
return
|
|
1132
|
+
|
|
1133
|
+
if filename is None:
|
|
1134
|
+
raise ValueError(f"{category} cannot process None")
|
|
1135
|
+
|
|
1111
1136
|
# Normalize value to string in case we receive a pathlib.Path
|
|
1112
1137
|
filename = str(filename)
|
|
1113
1138
|
|
|
@@ -1132,8 +1157,9 @@ class Chip:
|
|
|
1132
1157
|
use_filetype = filetype
|
|
1133
1158
|
|
|
1134
1159
|
if not use_fileset or not use_filetype:
|
|
1135
|
-
|
|
1136
|
-
|
|
1160
|
+
raise SiliconCompilerError(
|
|
1161
|
+
f'Unable to infer {category} fileset and/or filetype for '
|
|
1162
|
+
f'{filename} based on file extension.')
|
|
1137
1163
|
elif not quiet:
|
|
1138
1164
|
if not fileset and not filetype:
|
|
1139
1165
|
self.logger.info(f'{filename} inferred as {use_fileset}/{use_filetype}')
|
|
@@ -2695,18 +2721,25 @@ class Chip:
|
|
|
2695
2721
|
>>> chip._dashboard()
|
|
2696
2722
|
Opens a sesison of the dashboard.
|
|
2697
2723
|
'''
|
|
2698
|
-
|
|
2699
|
-
|
|
2724
|
+
if self._dash:
|
|
2725
|
+
# Remove previous dashboard
|
|
2726
|
+
self._dash.stop()
|
|
2727
|
+
self._dash = None
|
|
2728
|
+
|
|
2729
|
+
self._dash = Dashboard(self, port=port, graph_chips=graph_chips)
|
|
2730
|
+
self._dash.open_dashboard()
|
|
2731
|
+
|
|
2700
2732
|
if wait:
|
|
2701
2733
|
try:
|
|
2702
|
-
|
|
2734
|
+
self._dash.wait()
|
|
2703
2735
|
except KeyboardInterrupt:
|
|
2704
|
-
|
|
2736
|
+
self._dash._sleep()
|
|
2705
2737
|
finally:
|
|
2706
|
-
|
|
2738
|
+
self._dash.stop()
|
|
2739
|
+
self._dash = None
|
|
2707
2740
|
return None
|
|
2708
2741
|
|
|
2709
|
-
return
|
|
2742
|
+
return self._dash
|
|
2710
2743
|
|
|
2711
2744
|
###########################################################################
|
|
2712
2745
|
def summary(self, show_all_indices=False, generate_image=True, generate_html=True):
|
|
@@ -2746,8 +2779,8 @@ class Chip:
|
|
|
2746
2779
|
work_dir = self.getworkdir()
|
|
2747
2780
|
if os.path.isdir(work_dir):
|
|
2748
2781
|
# Mark file paths where the reports can be found if they were generated.
|
|
2749
|
-
results_html = os.path.join(work_dir, 'report.html')
|
|
2750
2782
|
results_img = os.path.join(work_dir, f'{self.design}.png')
|
|
2783
|
+
results_html = os.path.join(work_dir, 'report.html')
|
|
2751
2784
|
|
|
2752
2785
|
if generate_image:
|
|
2753
2786
|
_generate_summary_image(self, results_img)
|
|
@@ -2755,13 +2788,18 @@ class Chip:
|
|
|
2755
2788
|
if generate_html:
|
|
2756
2789
|
_generate_html_report(self, flow, nodes_to_execute, results_html)
|
|
2757
2790
|
|
|
2791
|
+
# dashboard does not generate any data
|
|
2792
|
+
self.logger.info(f'Dashboard at "sc-dashboard -cfg {work_dir}/{self.design}.pkg.json"')
|
|
2793
|
+
|
|
2758
2794
|
# Try to open the results and layout only if '-nodisplay' is not set.
|
|
2759
|
-
# Priority: PNG
|
|
2760
|
-
if
|
|
2795
|
+
# Priority: PNG > HTML > dashboard.
|
|
2796
|
+
if not self.get('option', 'nodisplay'):
|
|
2761
2797
|
if os.path.isfile(results_img):
|
|
2762
2798
|
_open_summary_image(results_img)
|
|
2763
2799
|
elif os.path.isfile(results_html):
|
|
2764
2800
|
_open_html_report(self, results_html)
|
|
2801
|
+
else:
|
|
2802
|
+
self._dashboard(wait=False)
|
|
2765
2803
|
|
|
2766
2804
|
###########################################################################
|
|
2767
2805
|
def clock(self, pin, period, jitter=0, mode='global'):
|
|
@@ -3258,6 +3296,9 @@ class Chip:
|
|
|
3258
3296
|
# Modules are not serializable, so save without cache
|
|
3259
3297
|
attributes['_showtools'] = {}
|
|
3260
3298
|
|
|
3299
|
+
# Dashboard is not serializable
|
|
3300
|
+
attributes['_dash'] = None
|
|
3301
|
+
|
|
3261
3302
|
# We have to remove the chip's logger before serializing the object
|
|
3262
3303
|
# since the logger object is not serializable.
|
|
3263
3304
|
del attributes['logger']
|
siliconcompiler/remote/client.py
CHANGED
|
@@ -178,7 +178,7 @@ def _log_truncated_stats(chip, status, nodes_with_status, nodes_to_print):
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
###################################
|
|
181
|
-
def _process_progress_info(chip, progress_info, nodes_to_print=3):
|
|
181
|
+
def _process_progress_info(chip, progress_info, recorded_nodes, all_nodes, nodes_to_print=3):
|
|
182
182
|
'''
|
|
183
183
|
Helper method to log information about a remote run's progress,
|
|
184
184
|
based on information returned from a 'check_progress/' call.
|
|
@@ -201,6 +201,11 @@ def _process_progress_info(chip, progress_info, nodes_to_print=3):
|
|
|
201
201
|
# collect completed
|
|
202
202
|
completed.append(node)
|
|
203
203
|
|
|
204
|
+
if node in all_nodes:
|
|
205
|
+
step, index = all_nodes[node]
|
|
206
|
+
if (step, index) not in recorded_nodes:
|
|
207
|
+
chip.set('record', 'status', status, step=step, index=index)
|
|
208
|
+
|
|
204
209
|
nodes_to_log = {key: nodes_to_log[key] for key in sorted(nodes_to_log.keys())}
|
|
205
210
|
|
|
206
211
|
# Log information about the job's progress.
|
|
@@ -360,11 +365,32 @@ def __remote_run_loop(chip, check_interval):
|
|
|
360
365
|
completed = []
|
|
361
366
|
result_procs = []
|
|
362
367
|
|
|
368
|
+
recorded = []
|
|
369
|
+
|
|
363
370
|
for step, index in nodes_to_execute(chip):
|
|
364
371
|
if SCNodeStatus.is_done(chip.get('record', 'status', step=step, index=index)):
|
|
365
372
|
continue
|
|
366
373
|
all_nodes[f'{step}{index}'] = (step, index)
|
|
367
374
|
|
|
375
|
+
def import_manifests():
|
|
376
|
+
changed = False
|
|
377
|
+
for step, index in all_nodes.values():
|
|
378
|
+
if (step, index) in recorded:
|
|
379
|
+
continue
|
|
380
|
+
|
|
381
|
+
manifest = os.path.join(chip.getworkdir(step=step, index=index),
|
|
382
|
+
'outputs',
|
|
383
|
+
f'{chip.design}.pkg.json')
|
|
384
|
+
if os.path.exists(manifest):
|
|
385
|
+
try:
|
|
386
|
+
chip.schema.read_journal(manifest)
|
|
387
|
+
recorded.append((step, index))
|
|
388
|
+
changed = True
|
|
389
|
+
except: # noqa E722
|
|
390
|
+
# Import may fail if file is still getting written
|
|
391
|
+
pass
|
|
392
|
+
return changed
|
|
393
|
+
|
|
368
394
|
def schedule_download(node):
|
|
369
395
|
node_proc = multiprocessor.Process(target=fetch_results,
|
|
370
396
|
args=(chip, node))
|
|
@@ -376,7 +402,12 @@ def __remote_run_loop(chip, check_interval):
|
|
|
376
402
|
|
|
377
403
|
while is_busy:
|
|
378
404
|
time.sleep(check_interval)
|
|
379
|
-
|
|
405
|
+
import_manifests()
|
|
406
|
+
new_completed, is_busy = check_progress(chip, recorded, all_nodes)
|
|
407
|
+
|
|
408
|
+
if chip._dash:
|
|
409
|
+
chip._dash.update_manifest()
|
|
410
|
+
|
|
380
411
|
nodes_to_fetch = []
|
|
381
412
|
for node in new_completed:
|
|
382
413
|
if node not in completed:
|
|
@@ -400,26 +431,26 @@ def __remote_run_loop(chip, check_interval):
|
|
|
400
431
|
proc.join()
|
|
401
432
|
|
|
402
433
|
# Read in node manifests
|
|
403
|
-
|
|
404
|
-
manifest = os.path.join(chip.getworkdir(step=step, index=index),
|
|
405
|
-
'outputs',
|
|
406
|
-
f'{chip.design}.pkg.json')
|
|
407
|
-
if os.path.exists(manifest):
|
|
408
|
-
chip.schema.read_journal(manifest)
|
|
434
|
+
import_manifests()
|
|
409
435
|
|
|
410
436
|
# Un-set the 'remote' option to avoid from/to-based summary/show errors
|
|
411
437
|
chip.unset('option', 'remote')
|
|
412
438
|
|
|
439
|
+
if chip._dash:
|
|
440
|
+
chip._dash.update_manifest()
|
|
441
|
+
|
|
413
442
|
|
|
414
443
|
###################################
|
|
415
|
-
def check_progress(chip):
|
|
444
|
+
def check_progress(chip, recorded_nodes, all_nodes):
|
|
416
445
|
try:
|
|
417
446
|
is_busy_info = is_job_busy(chip)
|
|
418
447
|
is_busy = is_busy_info['busy']
|
|
419
448
|
completed = []
|
|
420
449
|
if is_busy:
|
|
421
450
|
completed = _process_progress_info(chip,
|
|
422
|
-
is_busy_info
|
|
451
|
+
is_busy_info,
|
|
452
|
+
recorded_nodes,
|
|
453
|
+
all_nodes)
|
|
423
454
|
return completed, is_busy
|
|
424
455
|
except Exception as e:
|
|
425
456
|
# Sometimes an exception is raised if the request library cannot
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from .summary_image import _generate_summary_image, _open_summary_image
|
|
2
2
|
from .html_report import _generate_html_report, _open_html_report
|
|
3
3
|
from .summary_table import _show_summary_table
|
|
4
|
-
from .
|
|
4
|
+
from .dashboard import Dashboard
|
|
5
5
|
|
|
6
6
|
__all__ = [
|
|
7
7
|
"_generate_summary_image",
|
|
@@ -10,11 +10,20 @@ import multiprocessing
|
|
|
10
10
|
import subprocess
|
|
11
11
|
import atexit
|
|
12
12
|
import shutil
|
|
13
|
+
import fasteners
|
|
14
|
+
import signal
|
|
15
|
+
|
|
16
|
+
from siliconcompiler.report.dashboard import utils
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
class Dashboard():
|
|
16
20
|
__port = 8501
|
|
17
21
|
|
|
22
|
+
@staticmethod
|
|
23
|
+
def __signal_handler(signal, frame):
|
|
24
|
+
# used to avoid issues during shutdown
|
|
25
|
+
pass
|
|
26
|
+
|
|
18
27
|
def __init__(self, chip, port=None, graph_chips=None):
|
|
19
28
|
if not port:
|
|
20
29
|
port = Dashboard.__port
|
|
@@ -24,16 +33,18 @@ class Dashboard():
|
|
|
24
33
|
self.__directory = tempfile.mkdtemp(prefix='sc_dashboard_',
|
|
25
34
|
suffix=f'_{self.__chip.design}')
|
|
26
35
|
self.__manifest = os.path.join(self.__directory, 'manifest.json')
|
|
36
|
+
self.__manifest_lock = os.path.join(self.__directory, 'manifest.lock')
|
|
27
37
|
self.__port = port
|
|
28
38
|
dirname = os.path.dirname(__file__)
|
|
29
|
-
self.__streamlit_file = os.path.join(dirname, '
|
|
39
|
+
self.__streamlit_file = os.path.join(dirname, 'viewer.py')
|
|
30
40
|
|
|
31
41
|
self.__streamlit_args = [
|
|
32
42
|
("browser.gatherUsageStats", False),
|
|
33
43
|
("browser.serverPort", self.__port),
|
|
34
44
|
("logger.level", 'error'),
|
|
35
45
|
("runner.fastReruns", True),
|
|
36
|
-
("server.port", self.__port)
|
|
46
|
+
("server.port", self.__port),
|
|
47
|
+
("client.toolbarMode", "viewer")
|
|
37
48
|
]
|
|
38
49
|
|
|
39
50
|
# pass in a json object called __graph_chips
|
|
@@ -42,20 +53,33 @@ class Dashboard():
|
|
|
42
53
|
|
|
43
54
|
# use of list is to preserve order
|
|
44
55
|
self.__graph_chips = []
|
|
45
|
-
|
|
56
|
+
graph_chips_config = []
|
|
46
57
|
if graph_chips:
|
|
47
58
|
for chip_object_and_name in graph_chips:
|
|
48
59
|
chip_file_path = \
|
|
49
60
|
os.path.join(self.__directory,
|
|
50
61
|
f"{chip_object_and_name['name']}.json")
|
|
51
|
-
self.__graph_chips.append({
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
self.__graph_chips.append({
|
|
63
|
+
'chip': chip_object_and_name['chip'],
|
|
64
|
+
'name': chip_file_path
|
|
65
|
+
})
|
|
66
|
+
graph_chips_config.append({
|
|
67
|
+
"path": chip_file_path,
|
|
68
|
+
"cwd": utils.get_chip_cwd(
|
|
69
|
+
chip_object_and_name['chip'],
|
|
70
|
+
chip_object_and_name['cfg_path'])
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
self.__config = {
|
|
74
|
+
"manifest": self.__manifest,
|
|
75
|
+
"lock": self.__manifest_lock,
|
|
76
|
+
"graph_chips": graph_chips_config
|
|
77
|
+
}
|
|
57
78
|
|
|
58
79
|
self.__sleep_time = 0.5
|
|
80
|
+
self.__signal_handler = None
|
|
81
|
+
|
|
82
|
+
self.__lock = fasteners.InterProcessLock(self.__manifest_lock)
|
|
59
83
|
|
|
60
84
|
atexit.register(self.__cleanup)
|
|
61
85
|
|
|
@@ -70,10 +94,19 @@ class Dashboard():
|
|
|
70
94
|
self.__dashboard = multiprocessing.Process(
|
|
71
95
|
target=self._run_streamlit_bootstrap)
|
|
72
96
|
|
|
97
|
+
self.__signal_handler = signal.signal(signal.SIGINT, Dashboard.__signal_handler)
|
|
98
|
+
|
|
73
99
|
self.__dashboard.start()
|
|
74
100
|
|
|
75
101
|
def update_manifest(self):
|
|
76
|
-
self.
|
|
102
|
+
if not self.__manifest:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
new_file = f"{self.__manifest}.new.json"
|
|
106
|
+
self.__chip.write_manifest(new_file)
|
|
107
|
+
|
|
108
|
+
with self.__lock:
|
|
109
|
+
shutil.move(new_file, self.__manifest)
|
|
77
110
|
|
|
78
111
|
def update_graph_manifests(self):
|
|
79
112
|
for chip_object_and_name in self.__graph_chips:
|
|
@@ -103,8 +136,12 @@ class Dashboard():
|
|
|
103
136
|
self.__dashboard.terminate()
|
|
104
137
|
self._sleep()
|
|
105
138
|
|
|
139
|
+
if self.__signal_handler:
|
|
140
|
+
signal.signal(signal.SIGINT, self.__signal_handler)
|
|
141
|
+
|
|
106
142
|
self.__dashboard = None
|
|
107
143
|
self.__manifest = None
|
|
144
|
+
self.__signal_handler = None
|
|
108
145
|
|
|
109
146
|
def wait(self):
|
|
110
147
|
self.__dashboard.join()
|