siliconcompiler 0.34.2__py3-none-any.whl → 0.34.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/__init__.py +12 -5
- siliconcompiler/__main__.py +1 -7
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +104 -23
- siliconcompiler/apps/sc.py +4 -8
- siliconcompiler/apps/sc_dashboard.py +6 -4
- siliconcompiler/apps/sc_install.py +10 -6
- siliconcompiler/apps/sc_issue.py +7 -5
- siliconcompiler/apps/sc_remote.py +1 -1
- siliconcompiler/apps/sc_server.py +9 -14
- siliconcompiler/apps/sc_show.py +6 -5
- siliconcompiler/apps/smake.py +130 -94
- siliconcompiler/apps/utils/replay.py +4 -7
- siliconcompiler/apps/utils/summarize.py +3 -5
- siliconcompiler/asic.py +420 -0
- siliconcompiler/checklist.py +25 -2
- siliconcompiler/cmdlineschema.py +534 -0
- siliconcompiler/constraints/asic_component.py +2 -2
- siliconcompiler/constraints/asic_pins.py +2 -2
- siliconcompiler/constraints/asic_timing.py +3 -3
- siliconcompiler/core.py +7 -32
- siliconcompiler/data/templates/tcl/manifest.tcl.j2 +8 -0
- siliconcompiler/dependencyschema.py +89 -31
- siliconcompiler/design.py +176 -207
- siliconcompiler/filesetschema.py +250 -0
- siliconcompiler/flowgraph.py +274 -95
- siliconcompiler/fpga.py +124 -1
- siliconcompiler/library.py +218 -20
- siliconcompiler/metric.py +233 -20
- siliconcompiler/package/__init__.py +271 -50
- siliconcompiler/package/git.py +92 -16
- siliconcompiler/package/github.py +108 -12
- siliconcompiler/package/https.py +79 -16
- siliconcompiler/packageschema.py +88 -7
- siliconcompiler/pathschema.py +31 -2
- siliconcompiler/pdk.py +566 -1
- siliconcompiler/project.py +1095 -94
- siliconcompiler/record.py +38 -1
- siliconcompiler/remote/__init__.py +5 -2
- siliconcompiler/remote/client.py +11 -6
- siliconcompiler/remote/schema.py +5 -23
- siliconcompiler/remote/server.py +41 -54
- siliconcompiler/report/__init__.py +3 -3
- siliconcompiler/report/dashboard/__init__.py +48 -14
- siliconcompiler/report/dashboard/cli/__init__.py +99 -21
- siliconcompiler/report/dashboard/cli/board.py +364 -179
- siliconcompiler/report/dashboard/web/__init__.py +90 -12
- siliconcompiler/report/dashboard/web/components/__init__.py +219 -240
- siliconcompiler/report/dashboard/web/components/flowgraph.py +49 -26
- siliconcompiler/report/dashboard/web/components/graph.py +139 -100
- siliconcompiler/report/dashboard/web/layouts/__init__.py +29 -1
- siliconcompiler/report/dashboard/web/layouts/_common.py +38 -2
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph.py +39 -26
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_node_tab.py +50 -50
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_sac_tabs.py +49 -46
- siliconcompiler/report/dashboard/web/state.py +141 -14
- siliconcompiler/report/dashboard/web/utils/__init__.py +79 -16
- siliconcompiler/report/dashboard/web/utils/file_utils.py +74 -11
- siliconcompiler/report/dashboard/web/viewer.py +25 -1
- siliconcompiler/report/report.py +5 -2
- siliconcompiler/report/summary_image.py +29 -11
- siliconcompiler/scheduler/__init__.py +9 -1
- siliconcompiler/scheduler/docker.py +79 -1
- siliconcompiler/scheduler/run_node.py +35 -19
- siliconcompiler/scheduler/scheduler.py +208 -24
- siliconcompiler/scheduler/schedulernode.py +372 -46
- siliconcompiler/scheduler/send_messages.py +77 -29
- siliconcompiler/scheduler/slurm.py +76 -12
- siliconcompiler/scheduler/taskscheduler.py +140 -20
- siliconcompiler/schema/__init__.py +0 -2
- siliconcompiler/schema/baseschema.py +194 -38
- siliconcompiler/schema/journal.py +7 -4
- siliconcompiler/schema/namedschema.py +16 -10
- siliconcompiler/schema/parameter.py +55 -9
- siliconcompiler/schema/parametervalue.py +60 -0
- siliconcompiler/schema/safeschema.py +25 -2
- siliconcompiler/schema/schema_cfg.py +5 -5
- siliconcompiler/schema/utils.py +2 -2
- siliconcompiler/schema_obj.py +20 -3
- siliconcompiler/tool.py +979 -302
- siliconcompiler/tools/bambu/__init__.py +41 -0
- siliconcompiler/tools/builtin/concatenate.py +2 -2
- siliconcompiler/tools/builtin/minimum.py +2 -1
- siliconcompiler/tools/builtin/mux.py +2 -1
- siliconcompiler/tools/builtin/nop.py +2 -1
- siliconcompiler/tools/builtin/verify.py +2 -1
- siliconcompiler/tools/klayout/__init__.py +95 -0
- siliconcompiler/tools/openroad/__init__.py +289 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +7 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +8 -4
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +9 -5
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +5 -1
- siliconcompiler/tools/slang/__init__.py +1 -1
- siliconcompiler/tools/slang/elaborate.py +2 -1
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +1 -1
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +8 -1
- siliconcompiler/tools/vivado/syn_fpga.py +6 -0
- siliconcompiler/tools/vivado/vivado.py +35 -2
- siliconcompiler/tools/vpr/__init__.py +150 -0
- siliconcompiler/tools/yosys/__init__.py +369 -1
- siliconcompiler/tools/yosys/scripts/procs.tcl +0 -1
- siliconcompiler/toolscripts/_tools.json +5 -10
- siliconcompiler/utils/__init__.py +66 -0
- siliconcompiler/utils/flowgraph.py +2 -2
- siliconcompiler/utils/issue.py +2 -1
- siliconcompiler/utils/logging.py +14 -0
- siliconcompiler/utils/multiprocessing.py +256 -0
- siliconcompiler/utils/showtools.py +10 -0
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/METADATA +5 -5
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/RECORD +115 -118
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/entry_points.txt +3 -0
- siliconcompiler/schema/cmdlineschema.py +0 -250
- siliconcompiler/toolscripts/rhel8/install-slang.sh +0 -40
- siliconcompiler/toolscripts/rhel9/install-slang.sh +0 -40
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +0 -47
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +0 -37
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +0 -37
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.34.2.dist-info → siliconcompiler-0.34.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import re
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import os.path
|
|
6
|
+
|
|
7
|
+
from typing import Set, List
|
|
8
|
+
|
|
9
|
+
from siliconcompiler.schema import BaseSchema, EditableSchema, Parameter, Scope, PerNode
|
|
10
|
+
from siliconcompiler.schema.utils import trim
|
|
11
|
+
from siliconcompiler import _metadata
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CommandLineSchemaTmp:
|
|
15
|
+
'''
|
|
16
|
+
Class to provide the :meth:`create_cmdline` option to a schema object.
|
|
17
|
+
|
|
18
|
+
This class should not be instantiated by itself.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
class NewSchema(BaseSchema, CommandLineSchema):
|
|
22
|
+
creates a new class with the commandline options available
|
|
23
|
+
'''
|
|
24
|
+
|
|
25
|
+
###########################################################################
|
|
26
|
+
def create_cmdline(self,
|
|
27
|
+
progname,
|
|
28
|
+
description=None,
|
|
29
|
+
switchlist=None,
|
|
30
|
+
additional_args=None,
|
|
31
|
+
version=None,
|
|
32
|
+
print_banner=None,
|
|
33
|
+
input_map_handler=None,
|
|
34
|
+
preprocess_keys=None,
|
|
35
|
+
post_process=None,
|
|
36
|
+
logger=None):
|
|
37
|
+
"""Creates a Schema command line interface.
|
|
38
|
+
|
|
39
|
+
Exposes parameters in the SC schema as command line switches,
|
|
40
|
+
simplifying creation of SC apps with a restricted set of schema
|
|
41
|
+
parameters exposed at the command line. The order of command
|
|
42
|
+
line switch settings parsed from the command line is as follows:
|
|
43
|
+
|
|
44
|
+
1. loglevel, if available in schema
|
|
45
|
+
2. read_manifest([cfg]), if available in schema
|
|
46
|
+
3. read inputs with input_map_handler
|
|
47
|
+
4. all other switches
|
|
48
|
+
5. Run post_process
|
|
49
|
+
|
|
50
|
+
The cmdline interface is implemented using the Python argparse package
|
|
51
|
+
and the following use restrictions apply.
|
|
52
|
+
|
|
53
|
+
* Help is accessed with the '-h' switch.
|
|
54
|
+
* Arguments that include spaces must be enclosed with double quotes.
|
|
55
|
+
* List parameters are entered individually. (ie. -y libdir1 -y libdir2)
|
|
56
|
+
* For parameters with Boolean types, the switch implies "true".
|
|
57
|
+
* Special characters (such as '-') must be enclosed in double quotes.
|
|
58
|
+
* Compiler compatible switches include: -D, -I, -O{0,1,2,3}
|
|
59
|
+
* Legacy switch formats are supported: +libext+, +incdir+
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
progname (str): Name of program to be executed.
|
|
63
|
+
description (str): Short program description.
|
|
64
|
+
switchlist (list of str): List of SC parameter switches to expose
|
|
65
|
+
at the command line. By default all SC schema switches are
|
|
66
|
+
available. Parameter switches should be entered based on the
|
|
67
|
+
parameter 'switch' field in the schema. For parameters with
|
|
68
|
+
multiple switches, both will be accepted if any one is included
|
|
69
|
+
in this list.
|
|
70
|
+
input_map (dict of str): Dictionary mapping file extensions to input
|
|
71
|
+
filetypes. This is used to automatically assign positional
|
|
72
|
+
source arguments to ['input', 'fileset', ...] keypaths based on their file
|
|
73
|
+
extension. If None, the CLI will not accept positional source
|
|
74
|
+
arguments.
|
|
75
|
+
additional_args (dict of dict): Dictionary of extra arguments to add
|
|
76
|
+
to the command line parser, with the arguments matching the
|
|
77
|
+
argparse.add_argument() call.
|
|
78
|
+
version (str): Version to report when calling with -version
|
|
79
|
+
print_banner (function): Function callback to print command line banner
|
|
80
|
+
input_map_handler (function): Function callback handle inputs to the input map
|
|
81
|
+
preprocess_keys (function): Function callback to preprocess keys that need to be
|
|
82
|
+
corrected
|
|
83
|
+
post_process (function): Function callback to process arguments before returning
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
None if additional_args is not provided, otherwise a dictionary with the
|
|
87
|
+
command line options detected from the additional_args
|
|
88
|
+
|
|
89
|
+
Examples:
|
|
90
|
+
>>> schema.create_cmdline(progname='sc-show',switchlist=['-input','-cfg'])
|
|
91
|
+
Creates a command line interface for 'sc-show' app.
|
|
92
|
+
>>> schema.create_cmdline(progname='sc', input_map={'v': ('rtl', 'verilog')})
|
|
93
|
+
All sources ending in .v will be stored in ['input', 'rtl', 'verilog']
|
|
94
|
+
>>> extra = schema.create_cmdline(progname='sc',
|
|
95
|
+
additional_args={'-demo': {'action': 'store_true'}})
|
|
96
|
+
Returns extra = {'demo': False/True}
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
# Argparse
|
|
100
|
+
parser = argparse.ArgumentParser(prog=progname,
|
|
101
|
+
prefix_chars='-+',
|
|
102
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
103
|
+
description=description,
|
|
104
|
+
allow_abbrev=False)
|
|
105
|
+
|
|
106
|
+
# Create empty copy of schema
|
|
107
|
+
schema = type(self)()
|
|
108
|
+
|
|
109
|
+
# Track arguments
|
|
110
|
+
argument_map = {}
|
|
111
|
+
arguments = set()
|
|
112
|
+
|
|
113
|
+
# Iterate over all keys from an empty schema to add parser arguments
|
|
114
|
+
for keypath in sorted(schema.allkeys()):
|
|
115
|
+
param = schema.get(*keypath, field=None)
|
|
116
|
+
|
|
117
|
+
dest, switches = param.add_commandline_arguments(
|
|
118
|
+
parser,
|
|
119
|
+
*keypath,
|
|
120
|
+
switchlist=switchlist)
|
|
121
|
+
|
|
122
|
+
if switches:
|
|
123
|
+
argument_map[dest] = (keypath, param)
|
|
124
|
+
arguments.update(switches)
|
|
125
|
+
|
|
126
|
+
print_additional_arg_value = {}
|
|
127
|
+
if additional_args:
|
|
128
|
+
# Add additional user specified arguments
|
|
129
|
+
arg_dests = []
|
|
130
|
+
for arg, arg_detail in additional_args.items():
|
|
131
|
+
do_print = True
|
|
132
|
+
if "sc_print" in arg_detail:
|
|
133
|
+
do_print = arg_detail["sc_print"]
|
|
134
|
+
del arg_detail["sc_print"]
|
|
135
|
+
argument = parser.add_argument(arg, **arg_detail)
|
|
136
|
+
print_additional_arg_value[argument.dest] = do_print
|
|
137
|
+
|
|
138
|
+
arg_dests.append(argument.dest)
|
|
139
|
+
arguments.add(arg)
|
|
140
|
+
# rewrite additional_args with new dest information
|
|
141
|
+
additional_args = arg_dests
|
|
142
|
+
|
|
143
|
+
if version:
|
|
144
|
+
parser.add_argument('-version', action='version', version=version)
|
|
145
|
+
|
|
146
|
+
# Check if there are invalid switches
|
|
147
|
+
if switchlist:
|
|
148
|
+
for switch in switchlist:
|
|
149
|
+
if switch not in arguments:
|
|
150
|
+
raise ValueError(f'{switch} is not a valid commandline argument')
|
|
151
|
+
|
|
152
|
+
if input_map_handler:
|
|
153
|
+
parser.add_argument('source',
|
|
154
|
+
nargs='*',
|
|
155
|
+
help='Input files with filetype inferred by extension')
|
|
156
|
+
|
|
157
|
+
# Preprocess sys.argv to enable linux commandline switch formats
|
|
158
|
+
# (gcc, verilator, etc)
|
|
159
|
+
scargs = []
|
|
160
|
+
|
|
161
|
+
# Iterate from index 1, otherwise we end up with script name as a
|
|
162
|
+
# 'source' positional argument
|
|
163
|
+
for argument in sys.argv[1:]:
|
|
164
|
+
# Split switches with one character and a number after (O0,O1,O2)
|
|
165
|
+
opt = re.match(r'(\-\w)(\d+)', argument)
|
|
166
|
+
# Split assign switches (-DCFG_ASIC=1)
|
|
167
|
+
assign = re.search(r'(\-\w)(\w+\=\w+)', argument)
|
|
168
|
+
# Split plusargs (+incdir+/path)
|
|
169
|
+
plusarg = re.search(r'(\+\w+\+)(.*)', argument)
|
|
170
|
+
if opt:
|
|
171
|
+
scargs.append(opt.group(1))
|
|
172
|
+
scargs.append(opt.group(2))
|
|
173
|
+
elif plusarg:
|
|
174
|
+
scargs.append(plusarg.group(1))
|
|
175
|
+
scargs.append(plusarg.group(2))
|
|
176
|
+
elif assign:
|
|
177
|
+
scargs.append(assign.group(1))
|
|
178
|
+
scargs.append(assign.group(2))
|
|
179
|
+
else:
|
|
180
|
+
scargs.append(argument)
|
|
181
|
+
|
|
182
|
+
# Grab argument from pre-process sysargs
|
|
183
|
+
cmdargs = vars(parser.parse_args(scargs))
|
|
184
|
+
|
|
185
|
+
# Set loglevel if set at command line
|
|
186
|
+
do_print_banner = True
|
|
187
|
+
if 'option_loglevel' in cmdargs:
|
|
188
|
+
log_level = cmdargs['option_loglevel']
|
|
189
|
+
if isinstance(log_level, list):
|
|
190
|
+
# if multiple found, pick the first one
|
|
191
|
+
log_level = log_level[0]
|
|
192
|
+
if log_level == 'quiet':
|
|
193
|
+
do_print_banner = False
|
|
194
|
+
if logger:
|
|
195
|
+
logger.setLevel(log_level.split()[-1].upper())
|
|
196
|
+
|
|
197
|
+
if print_banner and do_print_banner:
|
|
198
|
+
print_banner()
|
|
199
|
+
|
|
200
|
+
extra_params = None
|
|
201
|
+
if additional_args:
|
|
202
|
+
# Grab user specified arguments
|
|
203
|
+
extra_params = {}
|
|
204
|
+
for arg in additional_args:
|
|
205
|
+
if arg in cmdargs:
|
|
206
|
+
val = cmdargs[arg]
|
|
207
|
+
if print_additional_arg_value[arg] and val and logger:
|
|
208
|
+
logger.info(
|
|
209
|
+
f'Command line argument entered: "{arg}" Value: {val}')
|
|
210
|
+
extra_params[arg] = val
|
|
211
|
+
# Remove from cmdargs
|
|
212
|
+
del cmdargs[arg]
|
|
213
|
+
|
|
214
|
+
# Read in all cfg files
|
|
215
|
+
if 'option_cfg' in cmdargs.keys():
|
|
216
|
+
for item in cmdargs['option_cfg']:
|
|
217
|
+
self.read_manifest(item)
|
|
218
|
+
|
|
219
|
+
if input_map_handler:
|
|
220
|
+
# Map sources to ['input'] keypath.
|
|
221
|
+
if 'source' in cmdargs:
|
|
222
|
+
input_map_handler(cmdargs['source'])
|
|
223
|
+
# we don't want to handle this in the next loop
|
|
224
|
+
del cmdargs['source']
|
|
225
|
+
|
|
226
|
+
# Cycle through all command args and write to manifest
|
|
227
|
+
for dest, vals in sorted(cmdargs.items(), key=lambda d: d[0]):
|
|
228
|
+
keypath, param = argument_map[dest]
|
|
229
|
+
|
|
230
|
+
# Turn everything into a list for uniformity
|
|
231
|
+
if not isinstance(vals, list):
|
|
232
|
+
vals = [vals]
|
|
233
|
+
|
|
234
|
+
# Cycle through all items
|
|
235
|
+
for item in vals:
|
|
236
|
+
if preprocess_keys:
|
|
237
|
+
item = preprocess_keys(keypath, item)
|
|
238
|
+
|
|
239
|
+
valkeypath, step, index, item = param.parse_commandline_arguments(item, *keypath)
|
|
240
|
+
|
|
241
|
+
if logger:
|
|
242
|
+
msg = f'Command line argument entered: [{",".join(valkeypath)}] Value: {item}'
|
|
243
|
+
if step is not None:
|
|
244
|
+
msg += f' step: {step}'
|
|
245
|
+
if index is not None:
|
|
246
|
+
msg += f' index: {index}'
|
|
247
|
+
logger.info(msg)
|
|
248
|
+
|
|
249
|
+
# Storing in manifest
|
|
250
|
+
if param.is_list():
|
|
251
|
+
self.add(*valkeypath, item, step=step, index=index)
|
|
252
|
+
else:
|
|
253
|
+
self.set(*valkeypath, item, step=step, index=index)
|
|
254
|
+
|
|
255
|
+
if post_process:
|
|
256
|
+
extra_params = post_process(cmdargs, extra_params)
|
|
257
|
+
|
|
258
|
+
return extra_params
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class CommandLineSchema(BaseSchema):
|
|
262
|
+
'''
|
|
263
|
+
Class to provide the :meth:`create_cmdline` option to a schema object.
|
|
264
|
+
|
|
265
|
+
This class should not be instantiated by itself.
|
|
266
|
+
|
|
267
|
+
Examples:
|
|
268
|
+
class NewSchema(BaseSchema, CommandLineSchema):
|
|
269
|
+
creates a new class with the commandline options available
|
|
270
|
+
'''
|
|
271
|
+
def _add_commandline_argument(self,
|
|
272
|
+
name: str,
|
|
273
|
+
type: str,
|
|
274
|
+
help: str,
|
|
275
|
+
switch: List[str] = None,
|
|
276
|
+
defvalue=None,
|
|
277
|
+
**kwargs):
|
|
278
|
+
'''
|
|
279
|
+
Adds a parameter to the commandline definition.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
name (str): name of parameter
|
|
283
|
+
type (str): schema type of the parameter
|
|
284
|
+
help (str): help string for this parameter
|
|
285
|
+
defvalue (any): default value for the parameter
|
|
286
|
+
'''
|
|
287
|
+
if isinstance(help, str):
|
|
288
|
+
# grab first line for short help
|
|
289
|
+
help = trim(help)
|
|
290
|
+
shorthelp = help.splitlines()[0].strip()
|
|
291
|
+
else:
|
|
292
|
+
raise TypeError("help must be a string")
|
|
293
|
+
|
|
294
|
+
kwargs["scope"] = Scope.GLOBAL
|
|
295
|
+
kwargs["pernode"] = PerNode.NEVER
|
|
296
|
+
kwargs["shorthelp"] = shorthelp
|
|
297
|
+
kwargs["help"] = help
|
|
298
|
+
|
|
299
|
+
if switch is None:
|
|
300
|
+
switch = f"-{name} <{type}>"
|
|
301
|
+
|
|
302
|
+
if switch is not ... and not switch:
|
|
303
|
+
raise ValueError("switch is required")
|
|
304
|
+
|
|
305
|
+
if switch is ...:
|
|
306
|
+
switch = None
|
|
307
|
+
|
|
308
|
+
kwargs["switch"] = switch
|
|
309
|
+
if defvalue is not None:
|
|
310
|
+
kwargs["defvalue"] = defvalue
|
|
311
|
+
|
|
312
|
+
EditableSchema(self).insert("cmdarg", name, Parameter(type, **kwargs))
|
|
313
|
+
|
|
314
|
+
@classmethod
|
|
315
|
+
def create_cmdline(cls,
|
|
316
|
+
progname: str = None,
|
|
317
|
+
description: str = None,
|
|
318
|
+
switchlist: Set[str] = None,
|
|
319
|
+
version: str = None,
|
|
320
|
+
print_banner: bool = True,
|
|
321
|
+
use_cfg: bool = False,
|
|
322
|
+
use_sources: bool = True):
|
|
323
|
+
"""
|
|
324
|
+
Creates an SC command line interface.
|
|
325
|
+
|
|
326
|
+
Exposes parameters in the SC schema as command line switches,
|
|
327
|
+
simplifying creation of SC apps with a restricted set of schema
|
|
328
|
+
parameters exposed at the command line. The order of command
|
|
329
|
+
line switch settings parsed from the command line is as follows:
|
|
330
|
+
|
|
331
|
+
1. read_manifest (-cfg), if specified by `use_cfg`
|
|
332
|
+
2. read commandline inputs
|
|
333
|
+
3. all other switches
|
|
334
|
+
|
|
335
|
+
The cmdline interface is implemented using the Python argparse package
|
|
336
|
+
and the following use restrictions apply.
|
|
337
|
+
|
|
338
|
+
* Help is accessed with the '-h' switch.
|
|
339
|
+
* Arguments that include spaces must be enclosed with double quotes.
|
|
340
|
+
* List parameters are entered individually. (ie. -y libdir1 -y libdir2)
|
|
341
|
+
* For parameters with Boolean types, the switch implies "true".
|
|
342
|
+
* Special characters (such as '-') must be enclosed in double quotes.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
progname (str): Name of program to be executed.
|
|
346
|
+
description (str): Short program description.
|
|
347
|
+
switchlist (list of str): List of SC parameter switches to expose
|
|
348
|
+
at the command line. By default all SC schema switches are
|
|
349
|
+
available. Parameter switches should be entered based on the
|
|
350
|
+
parameter 'switch' field in the schema. For parameters with
|
|
351
|
+
multiple switches, both will be accepted if any one is included
|
|
352
|
+
in this list.
|
|
353
|
+
version (str): version of this program.
|
|
354
|
+
print_banner (bool): if True, will print the siliconcompiler banner
|
|
355
|
+
use_cfg (bool): if True, add and parse the -cfg flag
|
|
356
|
+
use_sources (bool): if True, add positional arguments for files
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
new project object
|
|
360
|
+
|
|
361
|
+
Examples:
|
|
362
|
+
>>> chip.create_cmdline(progname='sc-show',switchlist=['-input','-cfg'])
|
|
363
|
+
Creates a command line interface for 'sc-show' app.
|
|
364
|
+
|
|
365
|
+
>>> chip.create_cmdline(progname='sc')
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
if progname and os.path.isfile(progname):
|
|
369
|
+
progname = os.path.basename(progname)
|
|
370
|
+
|
|
371
|
+
parser = argparse.ArgumentParser(
|
|
372
|
+
prog=progname,
|
|
373
|
+
description=description,
|
|
374
|
+
prefix_chars='-+',
|
|
375
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
376
|
+
allow_abbrev=False)
|
|
377
|
+
|
|
378
|
+
cfg_file = None
|
|
379
|
+
if use_cfg:
|
|
380
|
+
parser.add_argument(
|
|
381
|
+
'-cfg',
|
|
382
|
+
metavar='<file>',
|
|
383
|
+
help="configuration manifest")
|
|
384
|
+
|
|
385
|
+
# Grab config from argv
|
|
386
|
+
try:
|
|
387
|
+
cfg_index = sys.argv.index("-cfg", 1)
|
|
388
|
+
if cfg_index < len(sys.argv):
|
|
389
|
+
cfg_file = sys.argv[cfg_index + 1]
|
|
390
|
+
except ValueError:
|
|
391
|
+
pass
|
|
392
|
+
|
|
393
|
+
if cfg_file:
|
|
394
|
+
schema = cls.from_manifest(filepath=cfg_file)
|
|
395
|
+
else:
|
|
396
|
+
# Create new schema
|
|
397
|
+
schema = cls()
|
|
398
|
+
|
|
399
|
+
# Create empty schema for parameter generation
|
|
400
|
+
keyschema = schema.__class__()
|
|
401
|
+
|
|
402
|
+
if use_sources:
|
|
403
|
+
# Add commandline key for input files
|
|
404
|
+
if not isinstance(schema, CommandLineSchema):
|
|
405
|
+
raise TypeError("Schema is not a commandline class")
|
|
406
|
+
if "cmdarg" not in schema.getkeys() or "file" not in schema.getkeys("cmdarg"):
|
|
407
|
+
schema._add_commandline_argument("input", "[file]", "input files", ...)
|
|
408
|
+
keyschema._add_commandline_argument("input", "[file]", "input files", ...)
|
|
409
|
+
|
|
410
|
+
# Get logger if available
|
|
411
|
+
logger = getattr(schema, "logger", None)
|
|
412
|
+
|
|
413
|
+
# Track arguments
|
|
414
|
+
argumentmap = {}
|
|
415
|
+
arguments = set()
|
|
416
|
+
|
|
417
|
+
# Iterate over all keys from an empty schema to add parser arguments
|
|
418
|
+
for keypath in sorted(keyschema.allkeys()):
|
|
419
|
+
if keypath == ("option", "cfg"): # TODO: remove this when cfg is removed from schema
|
|
420
|
+
continue
|
|
421
|
+
|
|
422
|
+
param = keyschema.get(*keypath, field=None)
|
|
423
|
+
|
|
424
|
+
dest, switches = param.add_commandline_arguments(
|
|
425
|
+
parser,
|
|
426
|
+
*keypath,
|
|
427
|
+
switchlist=switchlist)
|
|
428
|
+
|
|
429
|
+
if switches:
|
|
430
|
+
argumentmap[dest] = (keypath, param)
|
|
431
|
+
arguments.update(switches)
|
|
432
|
+
|
|
433
|
+
# Check if there are invalid switches
|
|
434
|
+
if switchlist:
|
|
435
|
+
switchlist = set(switchlist)
|
|
436
|
+
unsed_switches = switchlist.difference(arguments)
|
|
437
|
+
if unsed_switches:
|
|
438
|
+
raise ValueError(f'{", ".join(unsed_switches)} is/are not a valid '
|
|
439
|
+
'commandline arguments')
|
|
440
|
+
|
|
441
|
+
prog_version = ""
|
|
442
|
+
if progname:
|
|
443
|
+
prog_version = f"{progname}"
|
|
444
|
+
if version is not None:
|
|
445
|
+
prog_version = f"{prog_version} {version}"
|
|
446
|
+
prog_version += " / "
|
|
447
|
+
|
|
448
|
+
parser.add_argument(
|
|
449
|
+
# '-v',
|
|
450
|
+
'-version',
|
|
451
|
+
# '--version',
|
|
452
|
+
action='version',
|
|
453
|
+
version=f"{prog_version}SiliconCompiler {_metadata.version}")
|
|
454
|
+
|
|
455
|
+
if use_sources:
|
|
456
|
+
parser.add_argument('source',
|
|
457
|
+
nargs='*',
|
|
458
|
+
help='Input files')
|
|
459
|
+
|
|
460
|
+
# Preprocess sys.argv to enable linux commandline switch formats
|
|
461
|
+
# (gcc, verilator, etc)
|
|
462
|
+
scargs = []
|
|
463
|
+
|
|
464
|
+
# Iterate from index 1, otherwise we end up with script name as a
|
|
465
|
+
# 'source' positional argument
|
|
466
|
+
for argument in sys.argv[1:]:
|
|
467
|
+
# Split switches with one character and a number after (O0,O1,O2)
|
|
468
|
+
opt = re.match(r'(\-\w)(\d+)', argument)
|
|
469
|
+
# Split assign switches (-DCFG_ASIC=1)
|
|
470
|
+
assign = re.search(r'(\-\w)(\w+\=\w+)', argument)
|
|
471
|
+
# Split plusargs (+incdir+/path)
|
|
472
|
+
plusarg = re.search(r'(\+\w+\+)(.*)', argument)
|
|
473
|
+
if opt:
|
|
474
|
+
scargs.append(opt.group(1))
|
|
475
|
+
scargs.append(opt.group(2))
|
|
476
|
+
elif plusarg:
|
|
477
|
+
scargs.append(plusarg.group(1))
|
|
478
|
+
scargs.append(plusarg.group(2))
|
|
479
|
+
elif assign:
|
|
480
|
+
scargs.append(assign.group(1))
|
|
481
|
+
scargs.append(assign.group(2))
|
|
482
|
+
else:
|
|
483
|
+
scargs.append(argument)
|
|
484
|
+
|
|
485
|
+
# Grab argument from pre-process sysargs
|
|
486
|
+
cmdargs = vars(parser.parse_args(scargs))
|
|
487
|
+
|
|
488
|
+
if print_banner:
|
|
489
|
+
print(_metadata.banner)
|
|
490
|
+
authors = []
|
|
491
|
+
for name in _metadata.authors:
|
|
492
|
+
name = name.split(" ")
|
|
493
|
+
authors.append(f"{name[0][0]}. {' '.join(name[1:])}")
|
|
494
|
+
print("Authors:", ", ".join(authors))
|
|
495
|
+
print("Version:", _metadata.version, "\n")
|
|
496
|
+
print("-" * 80)
|
|
497
|
+
|
|
498
|
+
if 'source' in cmdargs:
|
|
499
|
+
if cmdargs['source']:
|
|
500
|
+
schema.set("cmdarg", "input", cmdargs['source'])
|
|
501
|
+
# we don't want to handle this in the next loop
|
|
502
|
+
del cmdargs['source']
|
|
503
|
+
|
|
504
|
+
# Cycle through all command args and write to manifest
|
|
505
|
+
for dest, vals in list(sorted(cmdargs.items(), key=lambda d: d[0])):
|
|
506
|
+
if dest not in argumentmap:
|
|
507
|
+
continue
|
|
508
|
+
|
|
509
|
+
keypath, param = argumentmap[dest]
|
|
510
|
+
del cmdargs[dest]
|
|
511
|
+
|
|
512
|
+
# Turn everything into a list for uniformity
|
|
513
|
+
if not isinstance(vals, list):
|
|
514
|
+
vals = [vals]
|
|
515
|
+
|
|
516
|
+
# Cycle through all items
|
|
517
|
+
for item in vals:
|
|
518
|
+
valkeypath, step, index, item = param.parse_commandline_arguments(item, *keypath)
|
|
519
|
+
|
|
520
|
+
if logger:
|
|
521
|
+
msg = f'Command line argument entered: [{",".join(valkeypath)}] Value: {item}'
|
|
522
|
+
if step is not None:
|
|
523
|
+
msg += f' step: {step}'
|
|
524
|
+
if index is not None:
|
|
525
|
+
msg += f' index: {index}'
|
|
526
|
+
logger.info(msg)
|
|
527
|
+
|
|
528
|
+
# Storing in manifest
|
|
529
|
+
if param.is_list():
|
|
530
|
+
schema.add(*valkeypath, item, step=step, index=index)
|
|
531
|
+
else:
|
|
532
|
+
schema.set(*valkeypath, item, step=step, index=index)
|
|
533
|
+
|
|
534
|
+
return schema
|
|
@@ -281,10 +281,10 @@ class ASICComponentConstraints(BaseSchema):
|
|
|
281
281
|
if not isinstance(component, ASICComponentConstraint):
|
|
282
282
|
raise TypeError("component must be a component constraint object")
|
|
283
283
|
|
|
284
|
-
if component.name
|
|
284
|
+
if component.name is None:
|
|
285
285
|
raise ValueError("component constraint must have a name")
|
|
286
286
|
|
|
287
|
-
EditableSchema(self).insert(component.name
|
|
287
|
+
EditableSchema(self).insert(component.name, component, clobber=True)
|
|
288
288
|
|
|
289
289
|
def get_component(self, component: str = None):
|
|
290
290
|
"""
|
|
@@ -393,10 +393,10 @@ class ASICPinConstraints(BaseSchema):
|
|
|
393
393
|
if not isinstance(pin, ASICPinConstraint):
|
|
394
394
|
raise TypeError("pin must be a pin copnstraint object")
|
|
395
395
|
|
|
396
|
-
if pin.name
|
|
396
|
+
if pin.name is None:
|
|
397
397
|
raise ValueError("pin constraint must have a name")
|
|
398
398
|
|
|
399
|
-
EditableSchema(self).insert(pin.name
|
|
399
|
+
EditableSchema(self).insert(pin.name, pin, clobber=True)
|
|
400
400
|
|
|
401
401
|
def get_pinconstraint(self, pin: str = None):
|
|
402
402
|
"""
|
|
@@ -323,7 +323,7 @@ class ASICTimingScenarioSchema(NamedSchema):
|
|
|
323
323
|
a string.
|
|
324
324
|
"""
|
|
325
325
|
if isinstance(design, DesignSchema):
|
|
326
|
-
design = design.name
|
|
326
|
+
design = design.name
|
|
327
327
|
|
|
328
328
|
if not isinstance(design, str):
|
|
329
329
|
raise TypeError("design must be a design object or string")
|
|
@@ -420,10 +420,10 @@ class ASICTimingConstraintSchema(BaseSchema):
|
|
|
420
420
|
if not isinstance(scenario, ASICTimingScenarioSchema):
|
|
421
421
|
raise TypeError("scenario must be a timing scenario object")
|
|
422
422
|
|
|
423
|
-
if scenario.name
|
|
423
|
+
if scenario.name is None:
|
|
424
424
|
raise ValueError("scenario must have a name")
|
|
425
425
|
|
|
426
|
-
EditableSchema(self).insert(scenario.name
|
|
426
|
+
EditableSchema(self).insert(scenario.name, scenario, clobber=True)
|
|
427
427
|
|
|
428
428
|
def get_scenario(self, scenario: str = None):
|
|
429
429
|
"""
|
siliconcompiler/core.py
CHANGED
|
@@ -31,8 +31,7 @@ from siliconcompiler.report import _generate_summary_image, _open_summary_image
|
|
|
31
31
|
from siliconcompiler.report.dashboard.web import WebDashboard
|
|
32
32
|
from siliconcompiler.report.dashboard.cli import CliDashboard
|
|
33
33
|
from siliconcompiler.report.dashboard import DashboardType
|
|
34
|
-
import
|
|
35
|
-
from siliconcompiler.scheduler.scheduler import Scheduler
|
|
34
|
+
from siliconcompiler.scheduler import Scheduler, SchedulerNode
|
|
36
35
|
from siliconcompiler.utils.flowgraph import _check_flowgraph_io, _get_flowgraph_information
|
|
37
36
|
from siliconcompiler.tools._common import get_tool_task
|
|
38
37
|
from types import FunctionType, ModuleType
|
|
@@ -1790,6 +1789,7 @@ class Chip:
|
|
|
1790
1789
|
fout.write(template.render(manifest_dict='\n'.join(tcl_set_cmds),
|
|
1791
1790
|
scroot=os.path.abspath(
|
|
1792
1791
|
os.path.join(os.path.dirname(__file__))),
|
|
1792
|
+
toolvars={},
|
|
1793
1793
|
record_access=record,
|
|
1794
1794
|
record_access_id=Schema._RECORD_ACCESS_IDENTIFIER))
|
|
1795
1795
|
else:
|
|
@@ -2448,34 +2448,6 @@ class Chip:
|
|
|
2448
2448
|
else:
|
|
2449
2449
|
raise SiliconCompilerError(f'Failed to copy {path}', chip=self)
|
|
2450
2450
|
|
|
2451
|
-
###########################################################################
|
|
2452
|
-
def _archive_node(self, tar, step, index, include=None, verbose=True):
|
|
2453
|
-
if verbose:
|
|
2454
|
-
self.logger.info(f'Archiving {step}/{index}...')
|
|
2455
|
-
|
|
2456
|
-
basedir = self.getworkdir(step=step, index=index)
|
|
2457
|
-
|
|
2458
|
-
def arcname(path):
|
|
2459
|
-
return os.path.relpath(path, self.cwd)
|
|
2460
|
-
|
|
2461
|
-
if not os.path.isdir(basedir):
|
|
2462
|
-
if self.get('record', 'status', step=step, index=index) != NodeStatus.SKIPPED:
|
|
2463
|
-
self.logger.error(f'Unable to archive {step}/{index} due to missing node directory')
|
|
2464
|
-
return
|
|
2465
|
-
|
|
2466
|
-
if include:
|
|
2467
|
-
for pattern in include:
|
|
2468
|
-
for path in glob.iglob(os.path.join(basedir, pattern)):
|
|
2469
|
-
tar.add(path, arcname=arcname(path))
|
|
2470
|
-
else:
|
|
2471
|
-
for folder in ('reports', 'outputs'):
|
|
2472
|
-
path = os.path.join(basedir, folder)
|
|
2473
|
-
tar.add(path, arcname=arcname(path))
|
|
2474
|
-
|
|
2475
|
-
logfile = os.path.join(basedir, f'{step}.log')
|
|
2476
|
-
if os.path.isfile(logfile):
|
|
2477
|
-
tar.add(logfile, arcname=arcname(logfile))
|
|
2478
|
-
|
|
2479
2451
|
###########################################################################
|
|
2480
2452
|
def __archive_job(self, tar, job, flowgraph_nodes, index=None, include=None):
|
|
2481
2453
|
design = self.get('design')
|
|
@@ -2489,7 +2461,7 @@ class Chip:
|
|
|
2489
2461
|
self.logger.warning('Archiving job with failed or incomplete run.')
|
|
2490
2462
|
|
|
2491
2463
|
for (step, idx) in flowgraph_nodes:
|
|
2492
|
-
self
|
|
2464
|
+
SchedulerNode(self, step, idx).archive(tar, include=include)
|
|
2493
2465
|
|
|
2494
2466
|
###########################################################################
|
|
2495
2467
|
def archive(self, jobs=None, step=None, index=None, include=None, archive_name=None):
|
|
@@ -2961,7 +2933,7 @@ class Chip:
|
|
|
2961
2933
|
>>> run()
|
|
2962
2934
|
Runs the execution flow defined by the flowgraph dictionary.
|
|
2963
2935
|
'''
|
|
2964
|
-
from siliconcompiler.remote
|
|
2936
|
+
from siliconcompiler.remote import ClientScheduler
|
|
2965
2937
|
|
|
2966
2938
|
try:
|
|
2967
2939
|
if self.get('option', 'remote'):
|
|
@@ -3241,3 +3213,6 @@ class Chip:
|
|
|
3241
3213
|
|
|
3242
3214
|
def copy(self):
|
|
3243
3215
|
return copy.deepcopy(self)
|
|
3216
|
+
|
|
3217
|
+
def _init_run(self):
|
|
3218
|
+
pass
|
|
@@ -21,3 +21,11 @@ proc sc_root {} {
|
|
|
21
21
|
proc _sc_cfg_get_debug { args } {
|
|
22
22
|
{% if record_access %}puts "{{ record_access_id }} [join $args ,]"{% endif %}
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#############################################
|
|
27
|
+
# Tool variables
|
|
28
|
+
#############################################
|
|
29
|
+
|
|
30
|
+
{% for var, val in toolvars.items() %}set {{ var }} {{ val }}
|
|
31
|
+
{% endfor %}
|