siliconcompiler 0.33.2__py3-none-any.whl → 0.34.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/__init__.py +2 -0
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +1 -1
- siliconcompiler/apps/sc.py +1 -1
- siliconcompiler/apps/sc_issue.py +6 -4
- siliconcompiler/apps/sc_remote.py +3 -20
- siliconcompiler/apps/sc_show.py +2 -2
- siliconcompiler/apps/utils/replay.py +4 -4
- siliconcompiler/checklist.py +202 -1
- siliconcompiler/core.py +62 -293
- siliconcompiler/data/templates/email/general.j2 +3 -3
- siliconcompiler/data/templates/email/summary.j2 +1 -1
- siliconcompiler/data/templates/issue/README.txt +1 -1
- siliconcompiler/data/templates/report/sc_report.j2 +7 -7
- siliconcompiler/dependencyschema.py +392 -0
- siliconcompiler/design.py +758 -0
- siliconcompiler/flowgraph.py +79 -13
- siliconcompiler/optimizer/vizier.py +2 -2
- siliconcompiler/package/__init__.py +383 -223
- siliconcompiler/package/git.py +75 -77
- siliconcompiler/package/github.py +70 -97
- siliconcompiler/package/https.py +77 -93
- siliconcompiler/packageschema.py +260 -0
- siliconcompiler/pdk.py +5 -5
- siliconcompiler/remote/client.py +33 -15
- siliconcompiler/remote/server.py +2 -2
- siliconcompiler/report/dashboard/cli/__init__.py +6 -6
- siliconcompiler/report/dashboard/cli/board.py +4 -4
- siliconcompiler/report/dashboard/web/components/__init__.py +5 -5
- siliconcompiler/report/dashboard/web/components/flowgraph.py +4 -4
- siliconcompiler/report/dashboard/web/components/graph.py +2 -2
- siliconcompiler/report/dashboard/web/state.py +1 -1
- siliconcompiler/report/dashboard/web/utils/__init__.py +5 -5
- siliconcompiler/report/html_report.py +1 -1
- siliconcompiler/report/report.py +4 -4
- siliconcompiler/report/summary_table.py +2 -2
- siliconcompiler/report/utils.py +5 -5
- siliconcompiler/scheduler/__init__.py +3 -1382
- siliconcompiler/scheduler/docker.py +263 -0
- siliconcompiler/scheduler/run_node.py +10 -21
- siliconcompiler/scheduler/scheduler.py +311 -0
- siliconcompiler/scheduler/schedulernode.py +944 -0
- siliconcompiler/scheduler/send_messages.py +3 -3
- siliconcompiler/scheduler/slurm.py +149 -163
- siliconcompiler/scheduler/taskscheduler.py +45 -57
- siliconcompiler/schema/__init__.py +3 -3
- siliconcompiler/schema/baseschema.py +234 -11
- siliconcompiler/schema/editableschema.py +4 -0
- siliconcompiler/schema/journal.py +210 -0
- siliconcompiler/schema/namedschema.py +55 -2
- siliconcompiler/schema/parameter.py +14 -1
- siliconcompiler/schema/parametervalue.py +1 -34
- siliconcompiler/schema/schema_cfg.py +210 -349
- siliconcompiler/tool.py +412 -148
- siliconcompiler/tools/__init__.py +2 -0
- siliconcompiler/tools/builtin/_common.py +5 -5
- siliconcompiler/tools/builtin/concatenate.py +7 -7
- siliconcompiler/tools/builtin/minimum.py +4 -4
- siliconcompiler/tools/builtin/mux.py +4 -4
- siliconcompiler/tools/builtin/nop.py +4 -4
- siliconcompiler/tools/builtin/verify.py +8 -9
- siliconcompiler/tools/execute/exec_input.py +1 -1
- siliconcompiler/tools/genfasm/genfasm.py +1 -6
- siliconcompiler/tools/openroad/_apr.py +5 -1
- siliconcompiler/tools/openroad/antenna_repair.py +1 -1
- siliconcompiler/tools/openroad/macro_placement.py +1 -1
- siliconcompiler/tools/openroad/power_grid.py +1 -1
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +32 -25
- siliconcompiler/tools/opensta/timing.py +26 -3
- siliconcompiler/tools/slang/__init__.py +2 -2
- siliconcompiler/tools/surfer/__init__.py +0 -0
- siliconcompiler/tools/surfer/show.py +53 -0
- siliconcompiler/tools/surfer/surfer.py +30 -0
- siliconcompiler/tools/vpr/route.py +82 -0
- siliconcompiler/tools/vpr/vpr.py +23 -6
- siliconcompiler/tools/yosys/__init__.py +1 -1
- siliconcompiler/tools/yosys/scripts/procs.tcl +143 -0
- siliconcompiler/tools/yosys/{sc_synth_asic.tcl → scripts/sc_synth_asic.tcl} +4 -0
- siliconcompiler/tools/yosys/{sc_synth_fpga.tcl → scripts/sc_synth_fpga.tcl} +24 -77
- siliconcompiler/tools/yosys/syn_fpga.py +14 -0
- siliconcompiler/toolscripts/_tools.json +9 -13
- siliconcompiler/toolscripts/rhel9/install-vpr.sh +0 -2
- siliconcompiler/toolscripts/ubuntu22/install-surfer.sh +33 -0
- siliconcompiler/toolscripts/ubuntu24/install-surfer.sh +33 -0
- siliconcompiler/utils/__init__.py +4 -24
- siliconcompiler/utils/flowgraph.py +29 -28
- siliconcompiler/utils/issue.py +23 -29
- siliconcompiler/utils/logging.py +37 -7
- siliconcompiler/utils/showtools.py +6 -1
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/METADATA +16 -25
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/RECORD +98 -91
- siliconcompiler/scheduler/docker_runner.py +0 -254
- siliconcompiler/schema/journalingschema.py +0 -242
- siliconcompiler/tools/yosys/procs.tcl +0 -71
- siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +0 -68
- siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +0 -68
- siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +0 -68
- /siliconcompiler/tools/yosys/{sc_lec.tcl → scripts/sc_lec.tcl} +0 -0
- /siliconcompiler/tools/yosys/{sc_screenshot.tcl → scripts/sc_screenshot.tcl} +0 -0
- /siliconcompiler/tools/yosys/{syn_strategies.tcl → scripts/syn_strategies.tcl} +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/top_level.txt +0 -0
siliconcompiler/tool.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import contextlib
|
|
2
|
+
import copy
|
|
3
|
+
import csv
|
|
4
|
+
import gzip
|
|
2
5
|
import logging
|
|
3
6
|
import os
|
|
4
7
|
import psutil
|
|
@@ -8,6 +11,7 @@ import shutil
|
|
|
8
11
|
import subprocess
|
|
9
12
|
import sys
|
|
10
13
|
import time
|
|
14
|
+
import yaml
|
|
11
15
|
|
|
12
16
|
try:
|
|
13
17
|
import resource
|
|
@@ -25,12 +29,14 @@ import os.path
|
|
|
25
29
|
from packaging.version import Version, InvalidVersion
|
|
26
30
|
from packaging.specifiers import SpecifierSet, InvalidSpecifier
|
|
27
31
|
|
|
28
|
-
from siliconcompiler.schema import NamedSchema
|
|
32
|
+
from siliconcompiler.schema import NamedSchema, Journal
|
|
29
33
|
from siliconcompiler.schema import EditableSchema, Parameter, PerNode, Scope
|
|
34
|
+
from siliconcompiler.schema.parametertype import NodeType
|
|
30
35
|
from siliconcompiler.schema.utils import trim
|
|
31
36
|
|
|
32
|
-
from siliconcompiler import utils
|
|
37
|
+
from siliconcompiler import utils, NodeStatus
|
|
33
38
|
from siliconcompiler import sc_open
|
|
39
|
+
from siliconcompiler import Schema
|
|
34
40
|
|
|
35
41
|
from siliconcompiler.record import RecordTool
|
|
36
42
|
from siliconcompiler.flowgraph import RuntimeFlowgraph
|
|
@@ -61,13 +67,6 @@ class TaskExecutableNotFound(TaskError):
|
|
|
61
67
|
|
|
62
68
|
|
|
63
69
|
class TaskSchema(NamedSchema):
|
|
64
|
-
def __init__(self, name=None):
|
|
65
|
-
super().__init__(name=name)
|
|
66
|
-
|
|
67
|
-
schema_task(self)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class ToolSchema(NamedSchema):
|
|
71
70
|
__parse_version_check_str = r"""
|
|
72
71
|
(?P<operator>(==|!=|<=|>=|<|>|~=))
|
|
73
72
|
\s*
|
|
@@ -84,16 +83,27 @@ class ToolSchema(NamedSchema):
|
|
|
84
83
|
re.VERBOSE | re.IGNORECASE)
|
|
85
84
|
|
|
86
85
|
def __init__(self, name=None):
|
|
87
|
-
super().__init__(
|
|
86
|
+
super().__init__()
|
|
87
|
+
self.set_name(name)
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
schema_task(self)
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
self.__set_runtime(None)
|
|
92
|
+
|
|
93
|
+
@contextlib.contextmanager
|
|
94
|
+
def runtime(self, chip, step=None, index=None, relpath=None):
|
|
95
|
+
'''
|
|
96
|
+
Sets the runtime information needed to properly execute a task.
|
|
97
|
+
Note: unstable API
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
Args:
|
|
100
|
+
chip (:class:`Chip`): root schema for the runtime information
|
|
101
|
+
'''
|
|
102
|
+
obj_copy = copy.copy(self)
|
|
103
|
+
obj_copy.__set_runtime(chip, step=step, index=index, relpath=relpath)
|
|
104
|
+
yield obj_copy
|
|
95
105
|
|
|
96
|
-
def
|
|
106
|
+
def __set_runtime(self, chip, step=None, index=None, relpath=None):
|
|
97
107
|
'''
|
|
98
108
|
Sets the runtime information needed to properly execute a task.
|
|
99
109
|
Note: unstable API
|
|
@@ -104,22 +114,30 @@ class ToolSchema(NamedSchema):
|
|
|
104
114
|
self.__chip = None
|
|
105
115
|
self.__schema_full = None
|
|
106
116
|
self.__logger = None
|
|
117
|
+
self.__design_name = None
|
|
118
|
+
self.__design_top = None
|
|
119
|
+
self.__cwd = None
|
|
120
|
+
self.__relpath = relpath
|
|
107
121
|
if chip:
|
|
108
122
|
self.__chip = chip
|
|
109
123
|
self.__schema_full = chip.schema
|
|
110
124
|
self.__logger = chip.logger
|
|
125
|
+
self.__design_name = chip.design
|
|
126
|
+
self.__design_top = chip.top()
|
|
127
|
+
self.__cwd = chip.cwd
|
|
111
128
|
|
|
112
129
|
self.__step = step
|
|
113
130
|
self.__index = index
|
|
114
|
-
self.__tool = None
|
|
115
|
-
self.__task = None
|
|
116
131
|
|
|
117
132
|
self.__schema_record = None
|
|
118
133
|
self.__schema_metric = None
|
|
119
134
|
self.__schema_flow = None
|
|
135
|
+
self.__schema_flow_runtime = None
|
|
136
|
+
self.__schema_tool = None
|
|
120
137
|
if self.__schema_full:
|
|
121
138
|
self.__schema_record = self.__schema_full.get("record", field="schema")
|
|
122
139
|
self.__schema_metric = self.__schema_full.get("metric", field="schema")
|
|
140
|
+
self.__schema_tool = self._parent()._parent()
|
|
123
141
|
|
|
124
142
|
if not self.__step:
|
|
125
143
|
self.__step = self.__schema_full.get('arg', 'step')
|
|
@@ -133,8 +151,11 @@ class ToolSchema(NamedSchema):
|
|
|
133
151
|
if not flow:
|
|
134
152
|
raise RuntimeError("flow not specified")
|
|
135
153
|
self.__schema_flow = self.__schema_full.get("flowgraph", flow, field="schema")
|
|
136
|
-
|
|
137
|
-
self.
|
|
154
|
+
|
|
155
|
+
self.__schema_flow_runtime = RuntimeFlowgraph(
|
|
156
|
+
self.__schema_flow,
|
|
157
|
+
from_steps=set([step for step, _ in self.__schema_flow.get_entry_nodes()]),
|
|
158
|
+
prune_nodes=self.__schema_full.get('option', 'prune'))
|
|
138
159
|
|
|
139
160
|
def node(self):
|
|
140
161
|
'''
|
|
@@ -147,10 +168,10 @@ class ToolSchema(NamedSchema):
|
|
|
147
168
|
def tool(self):
|
|
148
169
|
'''
|
|
149
170
|
Returns:
|
|
150
|
-
|
|
171
|
+
tool name
|
|
151
172
|
'''
|
|
152
173
|
|
|
153
|
-
|
|
174
|
+
raise NotImplementedError("tool name must be implemented by the child class")
|
|
154
175
|
|
|
155
176
|
def task(self):
|
|
156
177
|
'''
|
|
@@ -158,7 +179,7 @@ class ToolSchema(NamedSchema):
|
|
|
158
179
|
task name
|
|
159
180
|
'''
|
|
160
181
|
|
|
161
|
-
|
|
182
|
+
raise NotImplementedError("task name must be implemented by the child class")
|
|
162
183
|
|
|
163
184
|
def logger(self):
|
|
164
185
|
'''
|
|
@@ -185,6 +206,10 @@ class ToolSchema(NamedSchema):
|
|
|
185
206
|
return self.__schema_metric
|
|
186
207
|
elif type == "flow":
|
|
187
208
|
return self.__schema_flow
|
|
209
|
+
elif type == "runtimeflow":
|
|
210
|
+
return self.__schema_flow_runtime
|
|
211
|
+
elif type == "tool":
|
|
212
|
+
return self.__schema_tool
|
|
188
213
|
else:
|
|
189
214
|
raise ValueError(f"{type} is not a schema section")
|
|
190
215
|
|
|
@@ -199,7 +224,7 @@ class ToolSchema(NamedSchema):
|
|
|
199
224
|
path to executable, or None if not specified
|
|
200
225
|
'''
|
|
201
226
|
|
|
202
|
-
exe = self.get('exe')
|
|
227
|
+
exe = self.schema("tool").get('exe')
|
|
203
228
|
|
|
204
229
|
if exe is None:
|
|
205
230
|
return None
|
|
@@ -226,7 +251,7 @@ class ToolSchema(NamedSchema):
|
|
|
226
251
|
version determined by :meth:`.parse_version`.
|
|
227
252
|
'''
|
|
228
253
|
|
|
229
|
-
veropt = self.get('vswitch')
|
|
254
|
+
veropt = self.schema("tool").get('vswitch')
|
|
230
255
|
if not veropt:
|
|
231
256
|
return None
|
|
232
257
|
|
|
@@ -239,7 +264,8 @@ class ToolSchema(NamedSchema):
|
|
|
239
264
|
cmdlist = [exe]
|
|
240
265
|
cmdlist.extend(veropt)
|
|
241
266
|
|
|
242
|
-
self.__logger.debug(f'Running {self.
|
|
267
|
+
self.__logger.debug(f'Running {self.tool()}/{self.task()} version check: '
|
|
268
|
+
f'{" ".join(cmdlist)}')
|
|
243
269
|
|
|
244
270
|
proc = subprocess.run(cmdlist,
|
|
245
271
|
stdin=subprocess.DEVNULL,
|
|
@@ -254,9 +280,11 @@ class ToolSchema(NamedSchema):
|
|
|
254
280
|
try:
|
|
255
281
|
version = self.parse_version(proc.stdout)
|
|
256
282
|
except NotImplementedError:
|
|
257
|
-
raise NotImplementedError(f'{self.
|
|
283
|
+
raise NotImplementedError(f'{self.tool()}/{self.task()} does not implement '
|
|
284
|
+
'parse_version()')
|
|
258
285
|
except Exception as e:
|
|
259
|
-
self.__logger.error(f'{self.
|
|
286
|
+
self.__logger.error(f'{self.tool()}/{self.task()} failed to parse version string: '
|
|
287
|
+
f'{proc.stdout}')
|
|
260
288
|
raise e from None
|
|
261
289
|
|
|
262
290
|
self.__logger.info(f"Tool '{exe_base}' found with version '{version}' "
|
|
@@ -277,7 +305,7 @@ class ToolSchema(NamedSchema):
|
|
|
277
305
|
|
|
278
306
|
'''
|
|
279
307
|
|
|
280
|
-
spec_sets = self.get('version', step=self.__step, index=self.__index)
|
|
308
|
+
spec_sets = self.schema("tool").get('version', step=self.__step, index=self.__index)
|
|
281
309
|
if not spec_sets:
|
|
282
310
|
# No requirement so always true
|
|
283
311
|
return True
|
|
@@ -286,7 +314,7 @@ class ToolSchema(NamedSchema):
|
|
|
286
314
|
split_specs = [s.strip() for s in spec_set.split(",") if s.strip()]
|
|
287
315
|
specs_list = []
|
|
288
316
|
for spec in split_specs:
|
|
289
|
-
match = re.match(
|
|
317
|
+
match = re.match(TaskSchema.__parse_version_check, spec)
|
|
290
318
|
if match is None:
|
|
291
319
|
self.__logger.warning(f'Invalid version specifier {spec}. '
|
|
292
320
|
f'Defaulting to =={spec}.')
|
|
@@ -300,15 +328,15 @@ class ToolSchema(NamedSchema):
|
|
|
300
328
|
try:
|
|
301
329
|
normalized_version = self.normalize_version(reported_version)
|
|
302
330
|
except Exception as e:
|
|
303
|
-
self.__logger.error(f'Unable to normalize version for {self.
|
|
331
|
+
self.__logger.error(f'Unable to normalize version for {self.tool()}/{self.task()}: '
|
|
304
332
|
f'{reported_version}')
|
|
305
333
|
raise e from None
|
|
306
334
|
|
|
307
335
|
try:
|
|
308
336
|
version = Version(normalized_version)
|
|
309
337
|
except InvalidVersion:
|
|
310
|
-
self.__logger.error(f'Version {normalized_version} reported by
|
|
311
|
-
'not match standard.')
|
|
338
|
+
self.__logger.error(f'Version {normalized_version} reported by '
|
|
339
|
+
f'{self.tool()}/{self.task()} does not match standard.')
|
|
312
340
|
return False
|
|
313
341
|
|
|
314
342
|
try:
|
|
@@ -316,7 +344,8 @@ class ToolSchema(NamedSchema):
|
|
|
316
344
|
f'{op}{self.normalize_version(ver)}' for op, ver in specs_list]
|
|
317
345
|
normalized_specs = ','.join(normalized_spec_list)
|
|
318
346
|
except Exception as e:
|
|
319
|
-
self.__logger.error(f'Unable to normalize versions for
|
|
347
|
+
self.__logger.error(f'Unable to normalize versions for '
|
|
348
|
+
f'{self.tool()}/{self.task()}: '
|
|
320
349
|
f'{",".join([f"{op}{ver}" for op, ver in specs_list])}')
|
|
321
350
|
raise e from None
|
|
322
351
|
|
|
@@ -331,7 +360,8 @@ class ToolSchema(NamedSchema):
|
|
|
331
360
|
return True
|
|
332
361
|
|
|
333
362
|
allowedstr = '; '.join(spec_sets)
|
|
334
|
-
self.__logger.error(f"Version check failed for {self.
|
|
363
|
+
self.__logger.error(f"Version check failed for {self.tool()}/{self.task()}. "
|
|
364
|
+
"Check installation.")
|
|
335
365
|
self.__logger.error(f"Found version {reported_version}, "
|
|
336
366
|
f"did not satisfy any version specifier set {allowedstr}.")
|
|
337
367
|
return False
|
|
@@ -353,19 +383,21 @@ class ToolSchema(NamedSchema):
|
|
|
353
383
|
envvars[env] = self.__schema_full.get('option', 'env', env)
|
|
354
384
|
|
|
355
385
|
# Add tool specific vars
|
|
356
|
-
for lic_env in self.getkeys('licenseserver'):
|
|
357
|
-
license_file = self.get('licenseserver', lic_env,
|
|
386
|
+
for lic_env in self.schema("tool").getkeys('licenseserver'):
|
|
387
|
+
license_file = self.schema("tool").get('licenseserver', lic_env,
|
|
388
|
+
step=self.__step, index=self.__index)
|
|
358
389
|
if license_file:
|
|
359
390
|
envvars[lic_env] = ':'.join(license_file)
|
|
360
391
|
|
|
361
392
|
if include_path:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
393
|
+
path = self.schema("tool").find_files(
|
|
394
|
+
"path", step=self.__step, index=self.__index,
|
|
395
|
+
packages=self.schema().get("package", field="schema").get_resolvers(),
|
|
396
|
+
cwd=self.__cwd,
|
|
397
|
+
missing_ok=True)
|
|
365
398
|
|
|
366
399
|
envvars["PATH"] = os.getenv("PATH", os.defpath)
|
|
367
400
|
|
|
368
|
-
path = path_param.get(field=None).resolve_path() # TODO: needs package search
|
|
369
401
|
if path:
|
|
370
402
|
envvars["PATH"] = path + os.pathsep + envvars["PATH"]
|
|
371
403
|
|
|
@@ -376,9 +408,8 @@ class ToolSchema(NamedSchema):
|
|
|
376
408
|
envvars[var] = val
|
|
377
409
|
|
|
378
410
|
# Add task specific vars
|
|
379
|
-
for env in self.getkeys(
|
|
380
|
-
envvars[env] = self.get(
|
|
381
|
-
step=self.__step, index=self.__index)
|
|
411
|
+
for env in self.getkeys("env"):
|
|
412
|
+
envvars[env] = self.get("env", env)
|
|
382
413
|
|
|
383
414
|
return envvars
|
|
384
415
|
|
|
@@ -391,19 +422,20 @@ class ToolSchema(NamedSchema):
|
|
|
391
422
|
'''
|
|
392
423
|
|
|
393
424
|
cmdargs = []
|
|
394
|
-
cmdargs.extend(self.get('task', self.__task, 'option',
|
|
395
|
-
step=self.__step, index=self.__index))
|
|
396
|
-
|
|
397
|
-
# Add scripts files / TODO:
|
|
398
|
-
scripts = self.__chip.find_files('tool', self.__tool, 'task', self.__task, 'script',
|
|
399
|
-
step=self.__step, index=self.__index)
|
|
400
|
-
|
|
401
|
-
cmdargs.extend(scripts)
|
|
402
|
-
|
|
403
425
|
try:
|
|
404
|
-
|
|
426
|
+
if self.__relpath:
|
|
427
|
+
args = []
|
|
428
|
+
for arg in self.runtime_options():
|
|
429
|
+
if os.path.isabs(arg) and os.path.exists(arg):
|
|
430
|
+
args.append(os.path.relpath(arg, self.__relpath))
|
|
431
|
+
else:
|
|
432
|
+
args.append(arg)
|
|
433
|
+
else:
|
|
434
|
+
args = self.runtime_options()
|
|
435
|
+
|
|
436
|
+
cmdargs.extend(args)
|
|
405
437
|
except Exception as e:
|
|
406
|
-
self.__logger.error(f'Failed to get runtime options for {self.
|
|
438
|
+
self.__logger.error(f'Failed to get runtime options for {self.tool()}/{self.task()}')
|
|
407
439
|
raise e from None
|
|
408
440
|
|
|
409
441
|
# Cleanup args
|
|
@@ -424,13 +456,13 @@ class ToolSchema(NamedSchema):
|
|
|
424
456
|
replay_opts["work_dir"] = workdir
|
|
425
457
|
replay_opts["exports"] = self.get_runtime_environmental_variables(include_path=include_path)
|
|
426
458
|
|
|
427
|
-
replay_opts["executable"] = self.get('exe')
|
|
459
|
+
replay_opts["executable"] = self.schema("tool").get('exe')
|
|
428
460
|
replay_opts["step"] = self.__step
|
|
429
461
|
replay_opts["index"] = self.__index
|
|
430
|
-
replay_opts["cfg_file"] = f"inputs/{self.
|
|
462
|
+
replay_opts["cfg_file"] = f"inputs/{self.__design_name}.pkg.json"
|
|
431
463
|
replay_opts["node_only"] = 0 if replay_opts["executable"] else 1
|
|
432
464
|
|
|
433
|
-
vswitch = self.get('vswitch')
|
|
465
|
+
vswitch = self.schema("tool").get('vswitch')
|
|
434
466
|
if vswitch:
|
|
435
467
|
replay_opts["version_flag"] = shlex.join(vswitch)
|
|
436
468
|
|
|
@@ -487,6 +519,66 @@ class ToolSchema(NamedSchema):
|
|
|
487
519
|
os.makedirs(os.path.join(workdir, 'outputs'), exist_ok=True)
|
|
488
520
|
os.makedirs(os.path.join(workdir, 'reports'), exist_ok=True)
|
|
489
521
|
|
|
522
|
+
def __write_yaml_manifest(self, fout, manifest):
|
|
523
|
+
class YamlIndentDumper(yaml.Dumper):
|
|
524
|
+
def increase_indent(self, flow=False, indentless=False):
|
|
525
|
+
return super().increase_indent(flow=flow, indentless=indentless)
|
|
526
|
+
|
|
527
|
+
fout.write(yaml.dump(manifest.getdict(), Dumper=YamlIndentDumper,
|
|
528
|
+
default_flow_style=False))
|
|
529
|
+
|
|
530
|
+
def __write_tcl_manifest(self, fout, manifest):
|
|
531
|
+
template = utils.get_file_template('tcl/manifest.tcl.j2')
|
|
532
|
+
tcl_set_cmds = []
|
|
533
|
+
for key in sorted(manifest.allkeys()):
|
|
534
|
+
# print out all non default values
|
|
535
|
+
if 'default' in key:
|
|
536
|
+
continue
|
|
537
|
+
|
|
538
|
+
param = manifest.get(*key, field=None)
|
|
539
|
+
|
|
540
|
+
# create a TCL dict
|
|
541
|
+
keystr = ' '.join([NodeType.to_tcl(keypart, 'str') for keypart in key])
|
|
542
|
+
|
|
543
|
+
valstr = param.gettcl(step=self.__step, index=self.__index)
|
|
544
|
+
if valstr is None:
|
|
545
|
+
continue
|
|
546
|
+
|
|
547
|
+
# Ensure empty values get something
|
|
548
|
+
if valstr == '':
|
|
549
|
+
valstr = '{}'
|
|
550
|
+
|
|
551
|
+
tcl_set_cmds.append(f"dict set sc_cfg {keystr} {valstr}")
|
|
552
|
+
|
|
553
|
+
if template:
|
|
554
|
+
fout.write(template.render(manifest_dict='\n'.join(tcl_set_cmds),
|
|
555
|
+
scroot=os.path.abspath(
|
|
556
|
+
os.path.join(os.path.dirname(__file__))),
|
|
557
|
+
record_access="get" in Journal.access(self).get_types(),
|
|
558
|
+
record_access_id=Schema._RECORD_ACCESS_IDENTIFIER))
|
|
559
|
+
else:
|
|
560
|
+
for cmd in tcl_set_cmds:
|
|
561
|
+
fout.write(cmd + '\n')
|
|
562
|
+
fout.write('\n')
|
|
563
|
+
|
|
564
|
+
def __write_csv_manifest(self, fout, manifest):
|
|
565
|
+
csvwriter = csv.writer(fout)
|
|
566
|
+
csvwriter.writerow(['Keypath', 'Value'])
|
|
567
|
+
|
|
568
|
+
for key in sorted(manifest.allkeys()):
|
|
569
|
+
keypath = ','.join(key)
|
|
570
|
+
param = manifest.get(*key, field=None)
|
|
571
|
+
if param.get(field="pernode").is_never():
|
|
572
|
+
value = param.get()
|
|
573
|
+
else:
|
|
574
|
+
value = param.get(step=self.__step, index=self.__index)
|
|
575
|
+
|
|
576
|
+
if isinstance(value, (set, list)):
|
|
577
|
+
for item in value:
|
|
578
|
+
csvwriter.writerow([keypath, item])
|
|
579
|
+
else:
|
|
580
|
+
csvwriter.writerow([keypath, value])
|
|
581
|
+
|
|
490
582
|
def write_task_manifest(self, directory, backup=True):
|
|
491
583
|
'''
|
|
492
584
|
Write the manifest needed for the task
|
|
@@ -496,7 +588,7 @@ class ToolSchema(NamedSchema):
|
|
|
496
588
|
backup (bool): if True and an existing manifest is found a backup is kept.
|
|
497
589
|
'''
|
|
498
590
|
|
|
499
|
-
suffix = self.get('format')
|
|
591
|
+
suffix = self.schema("tool").get('format')
|
|
500
592
|
if not suffix:
|
|
501
593
|
return
|
|
502
594
|
|
|
@@ -505,8 +597,65 @@ class ToolSchema(NamedSchema):
|
|
|
505
597
|
if backup and os.path.exists(manifest_path):
|
|
506
598
|
shutil.copyfile(manifest_path, f'{manifest_path}.bak')
|
|
507
599
|
|
|
508
|
-
#
|
|
509
|
-
self.
|
|
600
|
+
# Generate abs paths
|
|
601
|
+
schema = self.__abspath_schema()
|
|
602
|
+
|
|
603
|
+
if re.search(r'\.json(\.gz)?$', manifest_path):
|
|
604
|
+
schema.write_manifest(manifest_path)
|
|
605
|
+
else:
|
|
606
|
+
try:
|
|
607
|
+
# format specific dumping
|
|
608
|
+
if manifest_path.endswith('.gz'):
|
|
609
|
+
fout = gzip.open(manifest_path, 'wt', encoding='UTF-8')
|
|
610
|
+
elif re.search(r'\.csv$', manifest_path):
|
|
611
|
+
# Files written using csv library should be opened with newline=''
|
|
612
|
+
# https://docs.python.org/3/library/csv.html#id3
|
|
613
|
+
fout = open(manifest_path, 'w', newline='')
|
|
614
|
+
else:
|
|
615
|
+
fout = open(manifest_path, 'w')
|
|
616
|
+
|
|
617
|
+
if re.search(r'(\.yaml|\.yml)(\.gz)?$', manifest_path):
|
|
618
|
+
self.__write_yaml_manifest(fout, schema)
|
|
619
|
+
elif re.search(r'\.tcl(\.gz)?$', manifest_path):
|
|
620
|
+
self.__write_tcl_manifest(fout, schema)
|
|
621
|
+
elif re.search(r'\.csv(\.gz)?$', manifest_path):
|
|
622
|
+
self.__write_csv_manifest(fout, schema)
|
|
623
|
+
else:
|
|
624
|
+
raise ValueError(f"{manifest_path} is not a recognized path type")
|
|
625
|
+
finally:
|
|
626
|
+
fout.close()
|
|
627
|
+
|
|
628
|
+
def __abspath_schema(self):
|
|
629
|
+
root = self.schema()
|
|
630
|
+
schema = root.copy()
|
|
631
|
+
|
|
632
|
+
strict = root.get("option", "strict")
|
|
633
|
+
root.set("option", "strict", False)
|
|
634
|
+
|
|
635
|
+
for keypath in root.allkeys():
|
|
636
|
+
paramtype = schema.get(*keypath, field='type')
|
|
637
|
+
if 'file' not in paramtype and 'dir' not in paramtype:
|
|
638
|
+
# only do something if type is file or dir
|
|
639
|
+
continue
|
|
640
|
+
|
|
641
|
+
for value, step, index in root.get(*keypath, field=None).getvalues():
|
|
642
|
+
if not value:
|
|
643
|
+
continue
|
|
644
|
+
abspaths = root.find_files(*keypath, missing_ok=True, step=step, index=index)
|
|
645
|
+
if isinstance(abspaths, (set, list)) and None in abspaths:
|
|
646
|
+
# Lists may not contain None
|
|
647
|
+
schema.set(*keypath, [], step=step, index=index)
|
|
648
|
+
else:
|
|
649
|
+
if self.__relpath:
|
|
650
|
+
if isinstance(abspaths, (set, list)):
|
|
651
|
+
abspaths = [os.path.relpath(path, self.__relpath) for path in abspaths]
|
|
652
|
+
else:
|
|
653
|
+
abspaths = os.path.relpath(abspaths, self.__relpath)
|
|
654
|
+
schema.set(*keypath, abspaths, step=step, index=index)
|
|
655
|
+
|
|
656
|
+
root.set("option", "strict", strict)
|
|
657
|
+
|
|
658
|
+
return schema
|
|
510
659
|
|
|
511
660
|
def __get_io_file(self, io_type):
|
|
512
661
|
'''
|
|
@@ -515,10 +664,8 @@ class ToolSchema(NamedSchema):
|
|
|
515
664
|
Args:
|
|
516
665
|
io_type (str): name of io type
|
|
517
666
|
'''
|
|
518
|
-
suffix = self.get(
|
|
519
|
-
|
|
520
|
-
destination = self.get('task', self.__task, io_type, 'destination',
|
|
521
|
-
step=self.__step, index=self.__index)
|
|
667
|
+
suffix = self.get(io_type, "suffix")
|
|
668
|
+
destination = self.get(io_type, "destination")
|
|
522
669
|
|
|
523
670
|
io_file = None
|
|
524
671
|
io_log = False
|
|
@@ -526,7 +673,7 @@ class ToolSchema(NamedSchema):
|
|
|
526
673
|
io_file = f"{self.__step}.{suffix}"
|
|
527
674
|
io_log = True
|
|
528
675
|
elif destination == 'output':
|
|
529
|
-
io_file = os.path.join('outputs', f"{self.
|
|
676
|
+
io_file = os.path.join('outputs', f"{self.__design_top}.{suffix}")
|
|
530
677
|
elif destination == 'none':
|
|
531
678
|
io_file = os.devnull
|
|
532
679
|
|
|
@@ -565,13 +712,13 @@ class ToolSchema(NamedSchema):
|
|
|
565
712
|
TERMINATE_TIMEOUT = 5
|
|
566
713
|
|
|
567
714
|
terminate_process(proc.pid, timeout=TERMINATE_TIMEOUT)
|
|
568
|
-
self.__logger.info(f'Waiting for {self.
|
|
715
|
+
self.__logger.info(f'Waiting for {self.tool()}/{self.task()} to exit...')
|
|
569
716
|
try:
|
|
570
717
|
proc.wait(timeout=TERMINATE_TIMEOUT)
|
|
571
718
|
except subprocess.TimeoutExpired:
|
|
572
719
|
if proc.poll() is None:
|
|
573
|
-
self.__logger.warning(f'{self.
|
|
574
|
-
'seconds. Terminating...')
|
|
720
|
+
self.__logger.warning(f'{self.tool()}/{self.task()} did not exit within '
|
|
721
|
+
f'{TERMINATE_TIMEOUT} seconds. Terminating...')
|
|
575
722
|
terminate_process(proc.pid, timeout=TERMINATE_TIMEOUT)
|
|
576
723
|
|
|
577
724
|
def run_task(self, workdir, quiet, loglevel, breakpoint, nice, timeout):
|
|
@@ -642,7 +789,7 @@ class ToolSchema(NamedSchema):
|
|
|
642
789
|
contextlib.redirect_stdout(stdout_writer):
|
|
643
790
|
retcode = self.run()
|
|
644
791
|
except Exception as e:
|
|
645
|
-
self.__logger.error(f'Failed in run() for {self.
|
|
792
|
+
self.__logger.error(f'Failed in run() for {self.tool()}/{self.task()}: {e}')
|
|
646
793
|
utils.print_traceback(self.__logger, e)
|
|
647
794
|
raise e
|
|
648
795
|
finally:
|
|
@@ -690,9 +837,9 @@ class ToolSchema(NamedSchema):
|
|
|
690
837
|
retcode = pty.spawn([exe, *cmdlist], read)
|
|
691
838
|
else:
|
|
692
839
|
with open(stdout_file, 'w') as stdout_writer, \
|
|
693
|
-
open(stdout_file, 'r', errors='
|
|
840
|
+
open(stdout_file, 'r', errors='replace') as stdout_reader, \
|
|
694
841
|
open(stderr_file, 'w') as stderr_writer, \
|
|
695
|
-
open(stderr_file, 'r', errors='
|
|
842
|
+
open(stderr_file, 'r', errors='replace') as stderr_reader:
|
|
696
843
|
# if STDOUT and STDERR are to be redirected to the same file,
|
|
697
844
|
# use a single writer
|
|
698
845
|
if stderr_file == stdout_file:
|
|
@@ -789,7 +936,7 @@ class ToolSchema(NamedSchema):
|
|
|
789
936
|
|
|
790
937
|
# Remove runtime information
|
|
791
938
|
for key in list(state.keys()):
|
|
792
|
-
if key.startswith("
|
|
939
|
+
if key.startswith("_TaskSchema__"):
|
|
793
940
|
del state[key]
|
|
794
941
|
|
|
795
942
|
return state
|
|
@@ -798,10 +945,101 @@ class ToolSchema(NamedSchema):
|
|
|
798
945
|
self.__dict__ = state
|
|
799
946
|
|
|
800
947
|
# Reinit runtime information
|
|
801
|
-
self.
|
|
948
|
+
self.__set_runtime(None)
|
|
802
949
|
|
|
803
950
|
def get_output_files(self):
|
|
804
|
-
return set(self.get("
|
|
951
|
+
return set(self.get("output"))
|
|
952
|
+
|
|
953
|
+
def get_files_from_input_nodes(self):
|
|
954
|
+
"""
|
|
955
|
+
Returns a dictionary of files with the node they originated from
|
|
956
|
+
"""
|
|
957
|
+
|
|
958
|
+
nodes = self.schema("runtimeflow").get_nodes()
|
|
959
|
+
|
|
960
|
+
inputs = {}
|
|
961
|
+
for in_step, in_index in self.schema("flow").get(*self.node(), 'input'):
|
|
962
|
+
if (in_step, in_index) not in nodes:
|
|
963
|
+
# node has been pruned so will not provide anything
|
|
964
|
+
continue
|
|
965
|
+
|
|
966
|
+
in_tool = self.schema("flow").get(in_step, in_index, "tool")
|
|
967
|
+
in_task = self.schema("flow").get(in_step, in_index, "task")
|
|
968
|
+
|
|
969
|
+
task_obj = self.schema().get("tool", in_tool, "task", in_task, field="schema")
|
|
970
|
+
|
|
971
|
+
if self.schema("record").get('status', step=in_step, index=in_index) == \
|
|
972
|
+
NodeStatus.SKIPPED:
|
|
973
|
+
with task_obj.runtime(self.__chip, step=in_step, index=in_index) as task:
|
|
974
|
+
for file, nodes in task.get_files_from_input_nodes().items():
|
|
975
|
+
inputs.setdefault(file, []).extend(nodes)
|
|
976
|
+
continue
|
|
977
|
+
|
|
978
|
+
for output in NamedSchema.get(task_obj, "output", step=in_step, index=in_index):
|
|
979
|
+
inputs.setdefault(output, []).append((in_step, in_index))
|
|
980
|
+
|
|
981
|
+
return inputs
|
|
982
|
+
|
|
983
|
+
def compute_input_file_node_name(self, filename, step, index):
|
|
984
|
+
"""
|
|
985
|
+
Generate a unique name for in input file based on the originating node.
|
|
986
|
+
|
|
987
|
+
Args:
|
|
988
|
+
filename (str): name of inputfile
|
|
989
|
+
step (str): Step name
|
|
990
|
+
index (str): Index name
|
|
991
|
+
"""
|
|
992
|
+
|
|
993
|
+
_, file_type = os.path.splitext(filename)
|
|
994
|
+
|
|
995
|
+
if file_type:
|
|
996
|
+
base = filename
|
|
997
|
+
total_ext = []
|
|
998
|
+
while file_type:
|
|
999
|
+
base, file_type = os.path.splitext(base)
|
|
1000
|
+
total_ext.append(file_type)
|
|
1001
|
+
|
|
1002
|
+
total_ext.reverse()
|
|
1003
|
+
|
|
1004
|
+
return f'{base}.{step}{index}{"".join(total_ext)}'
|
|
1005
|
+
else:
|
|
1006
|
+
return f'{filename}.{step}{index}'
|
|
1007
|
+
|
|
1008
|
+
def add_parameter(self, name, type, help, defvalue=None):
|
|
1009
|
+
'''
|
|
1010
|
+
Adds a parameter to the task definition.
|
|
1011
|
+
|
|
1012
|
+
Args:
|
|
1013
|
+
name (str): name of parameter
|
|
1014
|
+
type (str): schema type of the parameter
|
|
1015
|
+
help (str): help string for this parameter
|
|
1016
|
+
defvalue (any): default value for the parameter
|
|
1017
|
+
'''
|
|
1018
|
+
help = trim(help)
|
|
1019
|
+
param = Parameter(
|
|
1020
|
+
type,
|
|
1021
|
+
defvalue=defvalue,
|
|
1022
|
+
scope=Scope.JOB,
|
|
1023
|
+
pernode=PerNode.OPTIONAL,
|
|
1024
|
+
shorthelp=help,
|
|
1025
|
+
help=help
|
|
1026
|
+
)
|
|
1027
|
+
|
|
1028
|
+
EditableSchema(self).insert("var", name, param)
|
|
1029
|
+
|
|
1030
|
+
return param
|
|
1031
|
+
|
|
1032
|
+
###############################################################
|
|
1033
|
+
def get(self, *keypath, field='value'):
|
|
1034
|
+
return super().get(*keypath, field=field,
|
|
1035
|
+
step=self.__step, index=self.__index)
|
|
1036
|
+
|
|
1037
|
+
def set(self, *args, field='value', clobber=True):
|
|
1038
|
+
return super().set(*args, field=field, clobber=clobber,
|
|
1039
|
+
step=self.__step, index=self.__index)
|
|
1040
|
+
|
|
1041
|
+
def add(self, *args, field='value'):
|
|
1042
|
+
return super().add(*args, field=field, step=self.__step, index=self.__index)
|
|
805
1043
|
|
|
806
1044
|
###############################################################
|
|
807
1045
|
def parse_version(self, stdout):
|
|
@@ -814,19 +1052,23 @@ class ToolSchema(NamedSchema):
|
|
|
814
1052
|
pass
|
|
815
1053
|
|
|
816
1054
|
def select_input_nodes(self):
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
flow,
|
|
820
|
-
from_steps=set([step for step, _ in flow.get_entry_nodes()]),
|
|
821
|
-
prune_nodes=self.__chip.get('option', 'prune'))
|
|
822
|
-
|
|
823
|
-
return runtime.get_node_inputs(self.__step, self.__index, record=self.schema("record"))
|
|
1055
|
+
return self.schema("runtimeflow").get_node_inputs(
|
|
1056
|
+
self.__step, self.__index, record=self.schema("record"))
|
|
824
1057
|
|
|
825
1058
|
def pre_process(self):
|
|
826
1059
|
pass
|
|
827
1060
|
|
|
828
1061
|
def runtime_options(self):
|
|
829
|
-
|
|
1062
|
+
cmdargs = []
|
|
1063
|
+
cmdargs.extend(self.get("option"))
|
|
1064
|
+
|
|
1065
|
+
# Add scripts files / TODO:
|
|
1066
|
+
scripts = self.__chip.find_files('tool', self.tool(), 'task', self.task(), 'script',
|
|
1067
|
+
step=self.__step, index=self.__index)
|
|
1068
|
+
|
|
1069
|
+
cmdargs.extend(scripts)
|
|
1070
|
+
|
|
1071
|
+
return cmdargs
|
|
830
1072
|
|
|
831
1073
|
def run(self):
|
|
832
1074
|
raise NotImplementedError("must be implemented by the implementation class")
|
|
@@ -835,10 +1077,34 @@ class ToolSchema(NamedSchema):
|
|
|
835
1077
|
pass
|
|
836
1078
|
|
|
837
1079
|
|
|
1080
|
+
class ToolSchema(NamedSchema):
|
|
1081
|
+
def __init__(self, name=None):
|
|
1082
|
+
super().__init__()
|
|
1083
|
+
self.set_name(name)
|
|
1084
|
+
|
|
1085
|
+
schema_tool(self)
|
|
1086
|
+
|
|
1087
|
+
schema = EditableSchema(self)
|
|
1088
|
+
schema.insert("task", "default", TaskSchema(None))
|
|
1089
|
+
|
|
1090
|
+
|
|
838
1091
|
###########################################################################
|
|
839
1092
|
# Migration helper
|
|
840
1093
|
###########################################################################
|
|
841
|
-
class ToolSchemaTmp(
|
|
1094
|
+
class ToolSchemaTmp(NamedSchema):
|
|
1095
|
+
def __init__(self):
|
|
1096
|
+
super().__init__()
|
|
1097
|
+
|
|
1098
|
+
schema_tool(self)
|
|
1099
|
+
|
|
1100
|
+
schema = EditableSchema(self)
|
|
1101
|
+
schema.insert("task", "default", TaskSchemaTmp())
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
class TaskSchemaTmp(TaskSchema):
|
|
1105
|
+
def __init__(self):
|
|
1106
|
+
super().__init__()
|
|
1107
|
+
|
|
842
1108
|
def __module_func(self, name, modules):
|
|
843
1109
|
for module in modules:
|
|
844
1110
|
method = getattr(module, name, None)
|
|
@@ -848,91 +1114,101 @@ class ToolSchemaTmp(ToolSchema):
|
|
|
848
1114
|
|
|
849
1115
|
def __tool_task_modules(self):
|
|
850
1116
|
step, index = self.node()
|
|
851
|
-
flow = self.
|
|
1117
|
+
flow = self._TaskSchema__chip.get('option', 'flow')
|
|
852
1118
|
return \
|
|
853
|
-
self.
|
|
854
|
-
self.
|
|
1119
|
+
self._TaskSchema__chip._get_tool_module(step, index, flow=flow), \
|
|
1120
|
+
self._TaskSchema__chip._get_task_module(step, index, flow=flow)
|
|
1121
|
+
|
|
1122
|
+
@contextlib.contextmanager
|
|
1123
|
+
def __in_step_index(self):
|
|
1124
|
+
prev_step, prev_index = self._TaskSchema__chip.get('arg', 'step'), \
|
|
1125
|
+
self._TaskSchema__chip.get('arg', 'index')
|
|
1126
|
+
step, index = self.node()
|
|
1127
|
+
self._TaskSchema__chip.set('arg', 'step', step)
|
|
1128
|
+
self._TaskSchema__chip.set('arg', 'index', index)
|
|
1129
|
+
yield
|
|
1130
|
+
self._TaskSchema__chip.set('arg', 'step', prev_step)
|
|
1131
|
+
self._TaskSchema__chip.set('arg', 'index', prev_index)
|
|
1132
|
+
|
|
1133
|
+
def tool(self):
|
|
1134
|
+
return self.schema("flow").get(*self.node(), 'tool')
|
|
1135
|
+
|
|
1136
|
+
def task(self):
|
|
1137
|
+
return self.schema("flow").get(*self.node(), 'task')
|
|
1138
|
+
|
|
1139
|
+
def get_exe(self):
|
|
1140
|
+
if self.tool() == "execute" and self.task() == "exec_input":
|
|
1141
|
+
return self.schema("tool").get("exe")
|
|
1142
|
+
return super().get_exe()
|
|
1143
|
+
|
|
1144
|
+
def schema(self, type=None):
|
|
1145
|
+
if type is None:
|
|
1146
|
+
return self._TaskSchema__chip
|
|
1147
|
+
return super().schema(type)
|
|
855
1148
|
|
|
856
1149
|
def get_output_files(self):
|
|
857
1150
|
_, task = self.__tool_task_modules()
|
|
858
1151
|
method = self.__module_func("_gather_outputs", [task])
|
|
859
1152
|
if method:
|
|
860
|
-
return method(self.
|
|
861
|
-
return
|
|
1153
|
+
return method(self._TaskSchema__chip, *self.node())
|
|
1154
|
+
return TaskSchema.get_output_files(self)
|
|
862
1155
|
|
|
863
1156
|
def parse_version(self, stdout):
|
|
864
1157
|
tool, _ = self.__tool_task_modules()
|
|
865
1158
|
method = self.__module_func("parse_version", [tool])
|
|
866
1159
|
if method:
|
|
867
1160
|
return method(stdout)
|
|
868
|
-
return
|
|
1161
|
+
return TaskSchema.parse_version(self, stdout)
|
|
869
1162
|
|
|
870
1163
|
def normalize_version(self, version):
|
|
871
1164
|
tool, _ = self.__tool_task_modules()
|
|
872
1165
|
method = self.__module_func("normalize_version", [tool])
|
|
873
1166
|
if method:
|
|
874
1167
|
return method(version)
|
|
875
|
-
return
|
|
1168
|
+
return TaskSchema.normalize_version(self, version)
|
|
1169
|
+
|
|
1170
|
+
def generate_replay_script(self, filepath, workdir, include_path=True):
|
|
1171
|
+
with self.__in_step_index():
|
|
1172
|
+
ret = TaskSchema.generate_replay_script(self, filepath, workdir,
|
|
1173
|
+
include_path=include_path)
|
|
1174
|
+
return ret
|
|
876
1175
|
|
|
877
1176
|
def setup(self):
|
|
878
1177
|
_, task = self.__tool_task_modules()
|
|
879
1178
|
method = self.__module_func("setup", [task])
|
|
880
1179
|
if method:
|
|
881
|
-
|
|
882
|
-
self.
|
|
883
|
-
step, index = self.node()
|
|
884
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
885
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
886
|
-
ret = method(self._ToolSchema__chip)
|
|
887
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
888
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1180
|
+
with self.__in_step_index():
|
|
1181
|
+
ret = method(self._TaskSchema__chip)
|
|
889
1182
|
return ret
|
|
890
|
-
return
|
|
1183
|
+
return TaskSchema.setup(self)
|
|
891
1184
|
|
|
892
1185
|
def select_input_nodes(self):
|
|
893
1186
|
_, task = self.__tool_task_modules()
|
|
894
1187
|
method = self.__module_func("_select_inputs", [task])
|
|
895
1188
|
if method:
|
|
896
|
-
|
|
897
|
-
self.
|
|
898
|
-
step, index = self.node()
|
|
899
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
900
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
901
|
-
ret = method(self._ToolSchema__chip, *self.node())
|
|
902
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
903
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1189
|
+
with self.__in_step_index():
|
|
1190
|
+
ret = method(self._TaskSchema__chip, *self.node())
|
|
904
1191
|
return ret
|
|
905
|
-
return
|
|
1192
|
+
return TaskSchema.select_input_nodes(self)
|
|
906
1193
|
|
|
907
1194
|
def pre_process(self):
|
|
908
1195
|
_, task = self.__tool_task_modules()
|
|
909
1196
|
method = self.__module_func("pre_process", [task])
|
|
910
1197
|
if method:
|
|
911
|
-
|
|
912
|
-
self.
|
|
913
|
-
step, index = self.node()
|
|
914
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
915
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
916
|
-
ret = method(self._ToolSchema__chip)
|
|
917
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
918
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1198
|
+
with self.__in_step_index():
|
|
1199
|
+
ret = method(self._TaskSchema__chip)
|
|
919
1200
|
return ret
|
|
920
|
-
return
|
|
1201
|
+
return TaskSchema.pre_process(self)
|
|
921
1202
|
|
|
922
1203
|
def runtime_options(self):
|
|
923
1204
|
tool, task = self.__tool_task_modules()
|
|
924
1205
|
method = self.__module_func("runtime_options", [task, tool])
|
|
925
1206
|
if method:
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
930
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
931
|
-
ret = method(self._ToolSchema__chip)
|
|
932
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
933
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1207
|
+
with self.__in_step_index():
|
|
1208
|
+
ret = TaskSchema.runtime_options(self)
|
|
1209
|
+
ret.extend(method(self._TaskSchema__chip))
|
|
934
1210
|
return ret
|
|
935
|
-
return
|
|
1211
|
+
return TaskSchema.runtime_options(self)
|
|
936
1212
|
|
|
937
1213
|
def run(self):
|
|
938
1214
|
_, task = self.__tool_task_modules()
|
|
@@ -940,38 +1216,26 @@ class ToolSchemaTmp(ToolSchema):
|
|
|
940
1216
|
if method:
|
|
941
1217
|
# Handle logger stdout suppression if quiet
|
|
942
1218
|
step, index = self.node()
|
|
943
|
-
stdout_handler_level = self.
|
|
944
|
-
if self.
|
|
945
|
-
self.
|
|
1219
|
+
stdout_handler_level = self._TaskSchema__chip._logger_console.level
|
|
1220
|
+
if self._TaskSchema__chip.get('option', 'quiet', step=step, index=index):
|
|
1221
|
+
self._TaskSchema__chip._logger_console.setLevel(logging.CRITICAL)
|
|
946
1222
|
|
|
947
|
-
|
|
948
|
-
self.
|
|
949
|
-
step, index = self.node()
|
|
950
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
951
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
952
|
-
retcode = method(self._ToolSchema__chip)
|
|
953
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
954
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1223
|
+
with self.__in_step_index():
|
|
1224
|
+
retcode = method(self._TaskSchema__chip)
|
|
955
1225
|
|
|
956
|
-
self.
|
|
1226
|
+
self._TaskSchema__chip._logger_console.setLevel(stdout_handler_level)
|
|
957
1227
|
|
|
958
1228
|
return retcode
|
|
959
|
-
return
|
|
1229
|
+
return TaskSchema.run(self)
|
|
960
1230
|
|
|
961
1231
|
def post_process(self):
|
|
962
1232
|
_, task = self.__tool_task_modules()
|
|
963
1233
|
method = self.__module_func("post_process", [task])
|
|
964
1234
|
if method:
|
|
965
|
-
|
|
966
|
-
self.
|
|
967
|
-
step, index = self.node()
|
|
968
|
-
self._ToolSchema__chip.set('arg', 'step', step)
|
|
969
|
-
self._ToolSchema__chip.set('arg', 'index', index)
|
|
970
|
-
ret = method(self._ToolSchema__chip)
|
|
971
|
-
self._ToolSchema__chip.set('arg', 'step', prev_step)
|
|
972
|
-
self._ToolSchema__chip.set('arg', 'index', prev_index)
|
|
1235
|
+
with self.__in_step_index():
|
|
1236
|
+
ret = method(self._TaskSchema__chip)
|
|
973
1237
|
return ret
|
|
974
|
-
return
|
|
1238
|
+
return TaskSchema.post_process(self)
|
|
975
1239
|
|
|
976
1240
|
|
|
977
1241
|
###########################################################################
|