siliconcompiler 0.33.0__py3-none-any.whl → 0.33.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siliconcompiler/_common.py +5 -0
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/sc_install.py +7 -0
- siliconcompiler/apps/sc_remote.py +7 -2
- siliconcompiler/core.py +34 -12
- siliconcompiler/metric.py +59 -0
- siliconcompiler/record.py +6 -2
- siliconcompiler/remote/client.py +10 -3
- siliconcompiler/remote/server.py +7 -2
- siliconcompiler/report/dashboard/cli/__init__.py +2 -0
- siliconcompiler/report/dashboard/cli/board.py +34 -30
- siliconcompiler/report/report.py +10 -5
- siliconcompiler/report/utils.py +12 -6
- siliconcompiler/scheduler/__init__.py +137 -974
- siliconcompiler/scheduler/send_messages.py +9 -3
- siliconcompiler/scheduler/slurm.py +10 -43
- siliconcompiler/scheduler/taskscheduler.py +320 -0
- siliconcompiler/schema/schema_cfg.py +2 -2
- siliconcompiler/tool.py +127 -19
- siliconcompiler/tools/_common/asic.py +5 -5
- siliconcompiler/tools/bluespec/convert.py +2 -1
- siliconcompiler/tools/builtin/_common.py +9 -2
- siliconcompiler/tools/builtin/concatenate.py +6 -2
- siliconcompiler/tools/builtin/minimum.py +7 -2
- siliconcompiler/tools/builtin/mux.py +7 -2
- siliconcompiler/tools/builtin/nop.py +7 -2
- siliconcompiler/tools/builtin/verify.py +7 -3
- siliconcompiler/tools/chisel/convert.py +10 -10
- siliconcompiler/tools/klayout/drc.py +2 -2
- siliconcompiler/tools/klayout/klayout_show.py +6 -6
- siliconcompiler/tools/klayout/klayout_utils.py +12 -12
- siliconcompiler/tools/netgen/count_lvs.py +2 -2
- siliconcompiler/tools/netgen/lvs.py +1 -1
- siliconcompiler/tools/openroad/_apr.py +2 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -7
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +18 -0
- siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -7
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +10 -0
- siliconcompiler/tools/opensta/timing.py +11 -0
- siliconcompiler/tools/slang/__init__.py +3 -3
- siliconcompiler/tools/slang/elaborate.py +6 -6
- siliconcompiler/tools/slang/lint.py +1 -3
- siliconcompiler/tools/vpr/_xml_constraint.py +8 -8
- siliconcompiler/tools/yosys/prepareLib.py +2 -2
- siliconcompiler/tools/yosys/sc_synth_asic.tcl +43 -1
- siliconcompiler/tools/yosys/screenshot.py +1 -1
- siliconcompiler/tools/yosys/syn_asic.py +5 -5
- siliconcompiler/toolscripts/_tools.json +8 -6
- siliconcompiler/toolscripts/rhel8/install-chisel.sh +9 -2
- siliconcompiler/toolscripts/rhel8/install-icarus.sh +10 -3
- siliconcompiler/toolscripts/rhel8/install-klayout.sh +8 -1
- siliconcompiler/toolscripts/rhel8/install-magic.sh +9 -2
- siliconcompiler/toolscripts/rhel8/install-montage.sh +1 -1
- siliconcompiler/toolscripts/rhel8/install-netgen.sh +9 -2
- siliconcompiler/toolscripts/rhel8/install-slang.sh +11 -4
- siliconcompiler/toolscripts/rhel8/install-surelog.sh +9 -2
- siliconcompiler/toolscripts/rhel8/install-sv2v.sh +11 -4
- siliconcompiler/toolscripts/rhel8/install-verible.sh +11 -3
- siliconcompiler/toolscripts/rhel8/install-verilator.sh +10 -3
- siliconcompiler/toolscripts/rhel8/install-xyce.sh +15 -10
- siliconcompiler/toolscripts/rhel9/install-chisel.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-ghdl.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +10 -3
- siliconcompiler/toolscripts/rhel9/install-icarus.sh +10 -3
- siliconcompiler/toolscripts/rhel9/install-klayout.sh +8 -1
- siliconcompiler/toolscripts/rhel9/install-magic.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-montage.sh +1 -1
- siliconcompiler/toolscripts/rhel9/install-netgen.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-openroad.sh +16 -3
- siliconcompiler/toolscripts/rhel9/install-opensta.sh +17 -5
- siliconcompiler/toolscripts/rhel9/install-slang.sh +11 -4
- siliconcompiler/toolscripts/rhel9/install-surelog.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-sv2v.sh +11 -4
- siliconcompiler/toolscripts/rhel9/install-verible.sh +11 -3
- siliconcompiler/toolscripts/rhel9/install-verilator.sh +10 -3
- siliconcompiler/toolscripts/rhel9/install-vpr.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-xdm.sh +10 -2
- siliconcompiler/toolscripts/rhel9/install-xyce.sh +15 -10
- siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +9 -2
- siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +10 -3
- siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +10 -2
- siliconcompiler/toolscripts/rhel9/install-yosys.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +10 -2
- siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +10 -3
- siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +8 -1
- siliconcompiler/toolscripts/ubuntu20/install-magic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-montage.sh +1 -1
- siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +16 -3
- siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +16 -5
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +11 -4
- siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +10 -2
- siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +11 -4
- siliconcompiler/toolscripts/ubuntu20/install-verible.sh +11 -3
- siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +10 -2
- siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +13 -8
- siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +10 -2
- siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +10 -3
- siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +8 -1
- siliconcompiler/toolscripts/ubuntu22/install-magic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-montage.sh +1 -1
- siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +16 -3
- siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +17 -5
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +11 -4
- siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +10 -2
- siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +11 -4
- siliconcompiler/toolscripts/ubuntu22/install-verible.sh +11 -3
- siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +10 -2
- siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +13 -8
- siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +10 -3
- siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +10 -2
- siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +12 -4
- siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +10 -3
- siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +8 -1
- siliconcompiler/toolscripts/ubuntu24/install-magic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-montage.sh +1 -1
- siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +16 -3
- siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +17 -5
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +11 -4
- siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +10 -2
- siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +11 -4
- siliconcompiler/toolscripts/ubuntu24/install-verible.sh +11 -3
- siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +10 -2
- siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +13 -8
- siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +9 -2
- siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +10 -3
- siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +10 -2
- siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +9 -2
- siliconcompiler/utils/__init__.py +11 -0
- siliconcompiler/utils/flowgraph.py +6 -101
- siliconcompiler/utils/issue.py +15 -23
- siliconcompiler/utils/logging.py +2 -2
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/METADATA +2 -2
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/RECORD +170 -169
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.1.dist-info}/top_level.txt +0 -0
|
@@ -10,8 +10,8 @@ from siliconcompiler import Schema
|
|
|
10
10
|
from siliconcompiler.report import utils as report_utils
|
|
11
11
|
import fastjsonschema
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from siliconcompiler.utils.flowgraph import nodes_to_execute
|
|
14
13
|
import uuid
|
|
14
|
+
from siliconcompiler.flowgraph import RuntimeFlowgraph
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
# Compile validation code for API request bodies.
|
|
@@ -25,7 +25,7 @@ with open(api_dir / 'email_credentials.json') as schema:
|
|
|
25
25
|
def __load_config(chip):
|
|
26
26
|
path = default_email_credentials_file()
|
|
27
27
|
if not os.path.exists(path):
|
|
28
|
-
chip.logger.
|
|
28
|
+
chip.logger.warning(f'Email credentials are not available: {path}')
|
|
29
29
|
return {}
|
|
30
30
|
|
|
31
31
|
with open(path) as f:
|
|
@@ -91,9 +91,15 @@ def send(chip, msg_type, step, index):
|
|
|
91
91
|
filename=os.path.basename(layout_img))
|
|
92
92
|
msg.attach(img_attach)
|
|
93
93
|
|
|
94
|
+
runtime = RuntimeFlowgraph(
|
|
95
|
+
chip.schema.get("flowgraph", flow, field='schema'),
|
|
96
|
+
from_steps=chip.get('option', 'from'),
|
|
97
|
+
to_steps=chip.get('option', 'to'),
|
|
98
|
+
prune_nodes=chip.get('option', 'prune'))
|
|
99
|
+
|
|
94
100
|
nodes, errors, metrics, metrics_unit, metrics_to_show, _ = \
|
|
95
101
|
report_utils._collect_data(chip, flow=flow,
|
|
96
|
-
flowgraph_nodes=
|
|
102
|
+
flowgraph_nodes=runtime.get_nodes())
|
|
97
103
|
|
|
98
104
|
text_msg = get_file_template('email/summary.j2').render(
|
|
99
105
|
design=chip.design,
|
|
@@ -2,13 +2,12 @@ import os
|
|
|
2
2
|
import shlex
|
|
3
3
|
import subprocess
|
|
4
4
|
import stat
|
|
5
|
-
import time
|
|
6
5
|
import uuid
|
|
7
6
|
import json
|
|
8
7
|
import shutil
|
|
9
8
|
from siliconcompiler import utils, SiliconCompilerError
|
|
10
|
-
from siliconcompiler.utils.flowgraph import nodes_to_execute
|
|
11
9
|
from siliconcompiler.package import get_cache_path
|
|
10
|
+
from siliconcompiler.flowgraph import RuntimeFlowgraph
|
|
12
11
|
|
|
13
12
|
# Full list of Slurm states, split into 'active' and 'inactive' categories.
|
|
14
13
|
# Many of these do not apply to a minimal configuration, but we'll track them all.
|
|
@@ -60,7 +59,14 @@ def init(chip):
|
|
|
60
59
|
collect = False
|
|
61
60
|
flow = chip.get('option', 'flow')
|
|
62
61
|
entry_nodes = chip.schema.get("flowgraph", flow, field="schema").get_entry_nodes()
|
|
63
|
-
|
|
62
|
+
|
|
63
|
+
runtime = RuntimeFlowgraph(
|
|
64
|
+
chip.schema.get("flowgraph", flow, field='schema'),
|
|
65
|
+
from_steps=chip.get('option', 'from'),
|
|
66
|
+
to_steps=chip.get('option', 'to'),
|
|
67
|
+
prune_nodes=chip.get('option', 'prune'))
|
|
68
|
+
|
|
69
|
+
for (step, index) in runtime.get_nodes():
|
|
64
70
|
if (step, index) in entry_nodes:
|
|
65
71
|
collect = True
|
|
66
72
|
|
|
@@ -125,7 +131,7 @@ def _defernode(chip, step, index, replay):
|
|
|
125
131
|
os.chmod(script_file,
|
|
126
132
|
os.stat(script_file).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
|
127
133
|
|
|
128
|
-
schedule_cmd = ['
|
|
134
|
+
schedule_cmd = ['srun',
|
|
129
135
|
'--exclusive',
|
|
130
136
|
'--partition', partition,
|
|
131
137
|
'--chdir', chip.cwd,
|
|
@@ -149,45 +155,6 @@ def _defernode(chip, step, index, replay):
|
|
|
149
155
|
# as it has closed its output stream. But if we don't call '.wait()',
|
|
150
156
|
# the '.returncode' value will not be set correctly.
|
|
151
157
|
step_result.wait()
|
|
152
|
-
result_msg = step_result.stdout.read().decode()
|
|
153
|
-
sbatch_id = result_msg.split(' ')[-1].strip()
|
|
154
|
-
retcode = 0
|
|
155
|
-
|
|
156
|
-
while True:
|
|
157
|
-
# Return early with an error if the batch ID is not an integer.
|
|
158
|
-
if not sbatch_id.isdigit():
|
|
159
|
-
retcode = 1
|
|
160
|
-
break
|
|
161
|
-
|
|
162
|
-
# Rate-limit the status checks to once every few seconds.
|
|
163
|
-
time.sleep(3.0)
|
|
164
|
-
|
|
165
|
-
# Check whether the job is still running.
|
|
166
|
-
jobcheck = subprocess.run(['scontrol', 'show', 'job', sbatch_id],
|
|
167
|
-
stdout=subprocess.PIPE,
|
|
168
|
-
stderr=subprocess.STDOUT)
|
|
169
|
-
jobout = jobcheck.stdout.decode()
|
|
170
|
-
|
|
171
|
-
# Jobs have a number of potential states that they can be in if they
|
|
172
|
-
# are still active in the Slurm scheduler.
|
|
173
|
-
if [state for state in SLURM_ACTIVE_STATES if state in jobout]:
|
|
174
|
-
pass
|
|
175
|
-
# 'COMPLETED' is a special case indicating successful job termination.
|
|
176
|
-
elif 'COMPLETED' in jobout:
|
|
177
|
-
break
|
|
178
|
-
elif 'Invalid job id specified' in jobout:
|
|
179
|
-
# May have already completed and been purged from active list.
|
|
180
|
-
break
|
|
181
|
-
# Jobs have a number of potential states that they can be in if they
|
|
182
|
-
# did not terminate successfully.
|
|
183
|
-
elif [state for state in SLURM_INACTIVE_STATES if state in jobout]:
|
|
184
|
-
# FAILED, TIMEOUT, etc.
|
|
185
|
-
retcode = 1
|
|
186
|
-
break
|
|
187
|
-
|
|
188
|
-
if retcode > 0:
|
|
189
|
-
chip.logger.error(f'srun command for {step} failed.')
|
|
190
|
-
chip.logger.error(f'srun output for {step}: {jobout}')
|
|
191
158
|
|
|
192
159
|
|
|
193
160
|
def _get_slurm_partition():
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import multiprocessing
|
|
2
|
+
import sys
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import os.path
|
|
6
|
+
|
|
7
|
+
from logging.handlers import QueueListener
|
|
8
|
+
|
|
9
|
+
from siliconcompiler import NodeStatus
|
|
10
|
+
from siliconcompiler import SiliconCompilerError
|
|
11
|
+
from siliconcompiler import utils
|
|
12
|
+
from siliconcompiler.flowgraph import RuntimeFlowgraph
|
|
13
|
+
|
|
14
|
+
from siliconcompiler.schema import JournalingSchema
|
|
15
|
+
|
|
16
|
+
from siliconcompiler.scheduler import slurm
|
|
17
|
+
from siliconcompiler.scheduler import docker_runner
|
|
18
|
+
from siliconcompiler.tools._common import get_tool_task
|
|
19
|
+
from siliconcompiler.utils.logging import SCBlankLoggerFormatter
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TaskScheduler:
|
|
23
|
+
__callbacks = {
|
|
24
|
+
"pre_run": lambda chip: None,
|
|
25
|
+
"pre_node": lambda chip, step, index: None,
|
|
26
|
+
"post_node": lambda chip, step, index: None,
|
|
27
|
+
"post_run": lambda chip: None,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def register_callback(hook, func):
|
|
32
|
+
if hook not in TaskScheduler.__callbacks:
|
|
33
|
+
raise ValueError(f"{hook} is not a valid callback")
|
|
34
|
+
TaskScheduler.__callbacks[hook] = func
|
|
35
|
+
|
|
36
|
+
def __init__(self, chip):
|
|
37
|
+
self.__chip = chip
|
|
38
|
+
self.__logger = self.__chip.logger
|
|
39
|
+
self.__schema = self.__chip.schema
|
|
40
|
+
self.__flow = self.__schema.get("flowgraph", self.__chip.get('option', 'flow'),
|
|
41
|
+
field="schema")
|
|
42
|
+
self.__record = self.__schema.get("record", field="schema")
|
|
43
|
+
self.__dashboard = chip._dash
|
|
44
|
+
|
|
45
|
+
self.__max_cores = utils.get_cores(chip)
|
|
46
|
+
self.__max_threads = utils.get_cores(chip)
|
|
47
|
+
self.__max_parallel_run = self.__chip.get('option', 'scheduler', 'maxnodes')
|
|
48
|
+
if not self.__max_parallel_run:
|
|
49
|
+
self.__max_parallel_run = utils.get_cores(chip)
|
|
50
|
+
# clip max parallel jobs to 1 <= jobs <= max_cores
|
|
51
|
+
self.__max_parallel_run = max(1, min(self.__max_parallel_run, self.__max_cores))
|
|
52
|
+
|
|
53
|
+
self.__log_queue = multiprocessing.Queue(-1)
|
|
54
|
+
|
|
55
|
+
self.__nodes = {}
|
|
56
|
+
self.__startTimes = {}
|
|
57
|
+
self.__dwellTime = 0.1
|
|
58
|
+
|
|
59
|
+
self.__create_nodes()
|
|
60
|
+
|
|
61
|
+
def __create_nodes(self):
|
|
62
|
+
from siliconcompiler.scheduler import _executenode, _runtask
|
|
63
|
+
|
|
64
|
+
runtime = RuntimeFlowgraph(
|
|
65
|
+
self.__flow,
|
|
66
|
+
from_steps=set([step for step, _ in self.__flow.get_entry_nodes()]),
|
|
67
|
+
prune_nodes=self.__chip.get('option', 'prune'))
|
|
68
|
+
|
|
69
|
+
init_funcs = set()
|
|
70
|
+
|
|
71
|
+
runtime_flow = RuntimeFlowgraph(
|
|
72
|
+
self.__flow,
|
|
73
|
+
from_steps=self.__chip.get('option', 'from'),
|
|
74
|
+
to_steps=self.__chip.get('option', 'to'),
|
|
75
|
+
prune_nodes=self.__chip.get('option', 'prune'))
|
|
76
|
+
|
|
77
|
+
for step, index in runtime_flow.get_nodes():
|
|
78
|
+
if self.__record.get('status', step=step, index=index) != NodeStatus.PENDING:
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
tool_name, task_name = get_tool_task(self.__chip, step, index)
|
|
82
|
+
threads = self.__chip.get('tool', tool_name, 'task', task_name, 'threads',
|
|
83
|
+
step=step, index=index)
|
|
84
|
+
if not threads:
|
|
85
|
+
threads = self.__max_threads
|
|
86
|
+
threads = max(1, min(threads, self.__max_threads))
|
|
87
|
+
|
|
88
|
+
task = {
|
|
89
|
+
"name": f"{step}{index}",
|
|
90
|
+
"inputs": runtime.get_node_inputs(step, index, record=self.__record),
|
|
91
|
+
"proc": None,
|
|
92
|
+
"child_pipe": None,
|
|
93
|
+
"parent_pipe": None,
|
|
94
|
+
"local": False,
|
|
95
|
+
"tool": tool_name,
|
|
96
|
+
"task": task_name,
|
|
97
|
+
"threads": threads,
|
|
98
|
+
"running": False,
|
|
99
|
+
"manifest": os.path.join(self.__chip.getworkdir(step=step, index=index),
|
|
100
|
+
'outputs',
|
|
101
|
+
f'{self.__chip.design}.pkg.json')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
exec_func = _executenode
|
|
105
|
+
|
|
106
|
+
node_scheduler = self.__chip.get('option', 'scheduler', 'name', step=step, index=index)
|
|
107
|
+
if node_scheduler == 'slurm':
|
|
108
|
+
# Defer job to compute node
|
|
109
|
+
# If the job is configured to run on a cluster, collect the schema
|
|
110
|
+
# and send it to a compute node for deferred execution.
|
|
111
|
+
init_funcs.add(slurm.init)
|
|
112
|
+
exec_func = slurm._defernode
|
|
113
|
+
elif node_scheduler == 'docker':
|
|
114
|
+
# Run job in docker
|
|
115
|
+
init_funcs.add(docker_runner.init)
|
|
116
|
+
exec_func = docker_runner.run
|
|
117
|
+
task["local"] = True
|
|
118
|
+
else:
|
|
119
|
+
task["local"] = True
|
|
120
|
+
|
|
121
|
+
task["parent_pipe"], task["child_pipe"] = multiprocessing.Pipe()
|
|
122
|
+
task["proc"] = multiprocessing.Process(
|
|
123
|
+
target=_runtask,
|
|
124
|
+
args=(self.__chip, self.__flow.name(), step, index, exec_func),
|
|
125
|
+
kwargs={"pipe": task["child_pipe"],
|
|
126
|
+
"queue": self.__log_queue})
|
|
127
|
+
|
|
128
|
+
self.__nodes[(step, index)] = task
|
|
129
|
+
|
|
130
|
+
# Call preprocessing for schedulers
|
|
131
|
+
for init_func in init_funcs:
|
|
132
|
+
init_func(self.__chip)
|
|
133
|
+
|
|
134
|
+
def run(self):
|
|
135
|
+
# Call this in case this was invoked without __main__
|
|
136
|
+
multiprocessing.freeze_support()
|
|
137
|
+
|
|
138
|
+
# Handle logs across threads
|
|
139
|
+
log_listener = QueueListener(self.__log_queue, self.__logger._console)
|
|
140
|
+
console_format = self.__logger._console.formatter
|
|
141
|
+
self.__logger._console.setFormatter(SCBlankLoggerFormatter())
|
|
142
|
+
log_listener.start()
|
|
143
|
+
|
|
144
|
+
# Update dashboard before run begins
|
|
145
|
+
if self.__dashboard:
|
|
146
|
+
self.__dashboard.update_manifest()
|
|
147
|
+
|
|
148
|
+
TaskScheduler.__callbacks["pre_run"](self.__chip)
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
self.__run_loop()
|
|
152
|
+
except KeyboardInterrupt:
|
|
153
|
+
# exit immediately
|
|
154
|
+
log_listener.stop()
|
|
155
|
+
sys.exit(0)
|
|
156
|
+
|
|
157
|
+
TaskScheduler.__callbacks["post_run"](self.__chip)
|
|
158
|
+
|
|
159
|
+
# Cleanup logger
|
|
160
|
+
log_listener.stop()
|
|
161
|
+
self.__logger._console.setFormatter(console_format)
|
|
162
|
+
|
|
163
|
+
def __run_loop(self):
|
|
164
|
+
self.__startTimes = {None: time.time()}
|
|
165
|
+
|
|
166
|
+
while len(self.get_nodes_waiting_to_run()) > 0 or len(self.get_running_nodes()) > 0:
|
|
167
|
+
changed = self.__process_completed_nodes()
|
|
168
|
+
changed |= self.__lanuch_nodes()
|
|
169
|
+
|
|
170
|
+
if changed and self.__dashboard:
|
|
171
|
+
# Update dashboard if the manifest changed
|
|
172
|
+
self.__dashboard.update_manifest(payload={"starttimes": self.__startTimes})
|
|
173
|
+
|
|
174
|
+
running_nodes = self.get_running_nodes()
|
|
175
|
+
|
|
176
|
+
# Check for situation where we have stuff left to run but don't
|
|
177
|
+
# have any nodes running. This shouldn't happen, but we will get
|
|
178
|
+
# stuck in an infinite loop if it does, so we want to break out
|
|
179
|
+
# with an explicit error.
|
|
180
|
+
if len(self.get_nodes_waiting_to_run()) > 0 and len(running_nodes) == 0:
|
|
181
|
+
raise SiliconCompilerError(
|
|
182
|
+
'Nodes left to run, but no running nodes. From/to may be invalid.',
|
|
183
|
+
chip=self.__chip)
|
|
184
|
+
|
|
185
|
+
if len(running_nodes) == 1:
|
|
186
|
+
# if there is only one node running, just join the thread
|
|
187
|
+
self.__nodes[running_nodes[0]]["proc"].join()
|
|
188
|
+
elif len(running_nodes) > 1:
|
|
189
|
+
# if there are more than 1, join the first with a timeout
|
|
190
|
+
self.__nodes[running_nodes[0]]["proc"].join(timeout=self.__dwellTime)
|
|
191
|
+
|
|
192
|
+
def get_nodes(self):
|
|
193
|
+
return sorted(self.__nodes.keys())
|
|
194
|
+
|
|
195
|
+
def get_running_nodes(self):
|
|
196
|
+
nodes = []
|
|
197
|
+
for node, info in self.__nodes.items():
|
|
198
|
+
if info["running"]:
|
|
199
|
+
nodes.append(node)
|
|
200
|
+
return sorted(nodes)
|
|
201
|
+
|
|
202
|
+
def get_nodes_waiting_to_run(self):
|
|
203
|
+
nodes = []
|
|
204
|
+
for node, info in self.__nodes.items():
|
|
205
|
+
if not info["running"] and info["proc"]:
|
|
206
|
+
nodes.append(node)
|
|
207
|
+
return sorted(nodes)
|
|
208
|
+
|
|
209
|
+
def __process_completed_nodes(self):
|
|
210
|
+
changed = False
|
|
211
|
+
for node in self.get_running_nodes():
|
|
212
|
+
info = self.__nodes[node]
|
|
213
|
+
|
|
214
|
+
if not info["proc"].is_alive():
|
|
215
|
+
manifest = info["manifest"]
|
|
216
|
+
|
|
217
|
+
self.__logger.debug(f'{info["name"]} is complete merging: {manifest}')
|
|
218
|
+
|
|
219
|
+
if os.path.exists(manifest):
|
|
220
|
+
JournalingSchema(self.__schema).read_journal(manifest)
|
|
221
|
+
|
|
222
|
+
if info["parent_pipe"] and info["parent_pipe"].poll(1):
|
|
223
|
+
try:
|
|
224
|
+
packages = info["parent_pipe"].recv()
|
|
225
|
+
if isinstance(packages, dict):
|
|
226
|
+
self.__chip._packages.update(packages)
|
|
227
|
+
except: # noqa E722
|
|
228
|
+
pass
|
|
229
|
+
|
|
230
|
+
step, index = node
|
|
231
|
+
if info["proc"].exitcode > 0:
|
|
232
|
+
status = NodeStatus.ERROR
|
|
233
|
+
else:
|
|
234
|
+
status = self.__record.get('status', step=step, index=index)
|
|
235
|
+
if not status or status == NodeStatus.PENDING:
|
|
236
|
+
status = NodeStatus.ERROR
|
|
237
|
+
|
|
238
|
+
self.__record.set('status', status, step=step, index=index)
|
|
239
|
+
|
|
240
|
+
info["running"] = False
|
|
241
|
+
info["proc"] = None
|
|
242
|
+
|
|
243
|
+
changed = True
|
|
244
|
+
|
|
245
|
+
TaskScheduler.__callbacks['post_node'](self.__chip, step, index)
|
|
246
|
+
|
|
247
|
+
return changed
|
|
248
|
+
|
|
249
|
+
def __allow_start(self, node):
|
|
250
|
+
info = self.__nodes[node]
|
|
251
|
+
|
|
252
|
+
if not info["local"]:
|
|
253
|
+
# using a different scheduler, so allow
|
|
254
|
+
return True
|
|
255
|
+
|
|
256
|
+
running_nodes = self.get_running_nodes()
|
|
257
|
+
|
|
258
|
+
if len(running_nodes) >= self.__max_parallel_run:
|
|
259
|
+
# exceeding machine resources
|
|
260
|
+
return False
|
|
261
|
+
|
|
262
|
+
current_threads = sum([self.__nodes[run_node]["threads"] for run_node in running_nodes])
|
|
263
|
+
|
|
264
|
+
if info["threads"] + current_threads > self.__max_cores:
|
|
265
|
+
# delay until there are enough core available
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
# allow
|
|
269
|
+
return True
|
|
270
|
+
|
|
271
|
+
def __lanuch_nodes(self):
|
|
272
|
+
changed = False
|
|
273
|
+
for node in self.get_nodes_waiting_to_run():
|
|
274
|
+
# TODO: breakpoint logic:
|
|
275
|
+
# if node is breakpoint, then don't launch while len(running_nodes) > 0
|
|
276
|
+
|
|
277
|
+
info = self.__nodes[node]
|
|
278
|
+
step, index = node
|
|
279
|
+
|
|
280
|
+
ready = True
|
|
281
|
+
inputs = []
|
|
282
|
+
for in_step, in_index in info["inputs"]:
|
|
283
|
+
in_status = self.__record.get('status', step=in_step, index=in_index)
|
|
284
|
+
inputs.append(in_status)
|
|
285
|
+
|
|
286
|
+
if not NodeStatus.is_done(in_status):
|
|
287
|
+
ready = False
|
|
288
|
+
break
|
|
289
|
+
if NodeStatus.is_error(in_status) and info["tool"] != "builtin":
|
|
290
|
+
# Fail if any dependency failed for non-builtin task
|
|
291
|
+
self.__record.set("status", NodeStatus.ERROR, step=step, index=index)
|
|
292
|
+
|
|
293
|
+
# Fail if no dependency successfully finished for builtin task
|
|
294
|
+
if inputs:
|
|
295
|
+
any_success = any([status == NodeStatus.SUCCESS for status in inputs])
|
|
296
|
+
else:
|
|
297
|
+
any_success = True
|
|
298
|
+
if ready and info["tool"] == "builtin" and not any_success:
|
|
299
|
+
self.__record.set("status", NodeStatus.ERROR, step=step, index=index)
|
|
300
|
+
|
|
301
|
+
if self.__record.get('status', step=step, index=index) == NodeStatus.ERROR:
|
|
302
|
+
info["proc"] = None
|
|
303
|
+
continue
|
|
304
|
+
|
|
305
|
+
# If there are no dependencies left, launch this node and
|
|
306
|
+
# remove from nodes_to_run.
|
|
307
|
+
if ready and self.__allow_start(node):
|
|
308
|
+
self.__logger.debug(f'Launching {info["name"]}')
|
|
309
|
+
|
|
310
|
+
TaskScheduler.__callbacks['pre_node'](self.__chip, step, index)
|
|
311
|
+
|
|
312
|
+
self.__record.set('status', NodeStatus.RUNNING, step=step, index=index)
|
|
313
|
+
self.__startTimes[node] = time.time()
|
|
314
|
+
changed = True
|
|
315
|
+
|
|
316
|
+
# Start the process
|
|
317
|
+
info["running"] = True
|
|
318
|
+
info["proc"].start()
|
|
319
|
+
|
|
320
|
+
return changed
|
|
@@ -1024,8 +1024,8 @@ def schema_flowgraph(cfg):
|
|
|
1024
1024
|
# Tool Setup
|
|
1025
1025
|
###########################################################################
|
|
1026
1026
|
def schema_tool(cfg):
|
|
1027
|
-
from siliconcompiler.tool import
|
|
1028
|
-
cfg.insert("tool", "default",
|
|
1027
|
+
from siliconcompiler.tool import ToolSchemaTmp
|
|
1028
|
+
cfg.insert("tool", "default", ToolSchemaTmp())
|
|
1029
1029
|
return cfg
|
|
1030
1030
|
|
|
1031
1031
|
|