siliconcompiler 0.29.0__py3-none-any.whl → 0.29.2__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/_metadata.py +1 -1
- siliconcompiler/apps/__init__.py +26 -0
- siliconcompiler/apps/sc_install.py +1 -1
- siliconcompiler/apps/utils/replay.py +96 -38
- siliconcompiler/checklists/__init__.py +12 -0
- siliconcompiler/core.py +85 -15
- siliconcompiler/flows/__init__.py +34 -0
- siliconcompiler/flows/showflow.py +1 -1
- siliconcompiler/libs/__init__.py +5 -0
- siliconcompiler/optimizer/__init__.py +199 -0
- siliconcompiler/optimizer/vizier.py +259 -0
- siliconcompiler/pdks/__init__.py +5 -0
- siliconcompiler/scheduler/__init__.py +67 -49
- siliconcompiler/scheduler/send_messages.py +1 -1
- siliconcompiler/schema/schema_cfg.py +2 -2
- siliconcompiler/schema/schema_obj.py +13 -10
- siliconcompiler/schema/utils.py +2 -0
- siliconcompiler/sphinx_ext/__init__.py +85 -0
- siliconcompiler/sphinx_ext/dynamicgen.py +17 -33
- siliconcompiler/sphinx_ext/schemagen.py +3 -2
- siliconcompiler/targets/__init__.py +26 -0
- siliconcompiler/templates/replay/replay.py.j2 +62 -0
- siliconcompiler/templates/replay/requirements.txt +2 -1
- siliconcompiler/templates/replay/setup.sh +119 -6
- siliconcompiler/tools/__init__.py +62 -0
- siliconcompiler/tools/_common/asic.py +77 -6
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +2 -2
- siliconcompiler/tools/ghdl/ghdl.py +1 -2
- siliconcompiler/tools/gtkwave/__init__.py +39 -0
- siliconcompiler/tools/gtkwave/scripts/sc_show.tcl +34 -0
- siliconcompiler/tools/gtkwave/show.py +70 -0
- siliconcompiler/tools/icarus/compile.py +4 -0
- siliconcompiler/tools/klayout/convert_drc_db.py +1 -1
- siliconcompiler/tools/klayout/drc.py +1 -1
- siliconcompiler/tools/klayout/export.py +8 -1
- siliconcompiler/tools/klayout/klayout.py +2 -2
- siliconcompiler/tools/klayout/klayout_convert_drc_db.py +2 -2
- siliconcompiler/tools/klayout/klayout_export.py +7 -5
- siliconcompiler/tools/klayout/klayout_operations.py +4 -3
- siliconcompiler/tools/klayout/klayout_show.py +3 -2
- siliconcompiler/tools/klayout/klayout_utils.py +1 -1
- siliconcompiler/tools/klayout/operations.py +8 -0
- siliconcompiler/tools/klayout/screenshot.py +6 -1
- siliconcompiler/tools/klayout/show.py +8 -1
- siliconcompiler/tools/magic/magic.py +1 -1
- siliconcompiler/tools/openroad/__init__.py +1 -1
- siliconcompiler/tools/openroad/_apr.py +11 -2
- siliconcompiler/tools/openroad/global_placement.py +23 -2
- siliconcompiler/tools/openroad/init_floorplan.py +1 -1
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +4 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +64 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +4 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +8 -2
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +88 -0
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +10 -1
- siliconcompiler/tools/openroad/scripts/sc_show.tcl +5 -0
- siliconcompiler/tools/opensta/__init__.py +1 -1
- siliconcompiler/tools/opensta/check_library.py +27 -0
- siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +255 -0
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +1 -1
- siliconcompiler/tools/sv2v/sv2v.py +1 -2
- siliconcompiler/tools/verilator/compile.py +11 -0
- siliconcompiler/tools/verilator/verilator.py +7 -8
- siliconcompiler/tools/vivado/vivado.py +1 -1
- siliconcompiler/tools/yosys/__init__.py +149 -0
- siliconcompiler/tools/yosys/lec.py +22 -9
- siliconcompiler/tools/yosys/sc_lec.tcl +94 -49
- siliconcompiler/tools/yosys/sc_syn.tcl +1 -0
- siliconcompiler/tools/yosys/screenshot.py +2 -2
- siliconcompiler/tools/yosys/syn_asic.py +98 -74
- siliconcompiler/tools/yosys/syn_asic.tcl +31 -6
- siliconcompiler/tools/yosys/syn_fpga.py +2 -3
- siliconcompiler/tools/yosys/syn_fpga.tcl +0 -1
- siliconcompiler/toolscripts/_tools.json +8 -3
- siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +40 -0
- siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +28 -0
- siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +28 -0
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +0 -0
- siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +29 -0
- siliconcompiler/utils/__init__.py +7 -3
- siliconcompiler/utils/showtools.py +3 -0
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/METADATA +14 -11
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/RECORD +88 -91
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/entry_points.txt +13 -0
- siliconcompiler/libs/asap7sc7p5t.py +0 -8
- siliconcompiler/libs/gf180mcu.py +0 -8
- siliconcompiler/libs/interposer.py +0 -8
- siliconcompiler/libs/nangate45.py +0 -8
- siliconcompiler/libs/sg13g2_stdcell.py +0 -8
- siliconcompiler/libs/sky130hd.py +0 -8
- siliconcompiler/libs/sky130io.py +0 -8
- siliconcompiler/pdks/asap7.py +0 -8
- siliconcompiler/pdks/freepdk45.py +0 -8
- siliconcompiler/pdks/gf180.py +0 -8
- siliconcompiler/pdks/ihp130.py +0 -8
- siliconcompiler/pdks/interposer.py +0 -8
- siliconcompiler/pdks/skywater130.py +0 -8
- siliconcompiler/templates/replay/run.py.j2 +0 -22
- siliconcompiler/tools/yosys/yosys.py +0 -148
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.29.0.dist-info → siliconcompiler-0.29.2.dist-info}/top_level.txt +0 -0
siliconcompiler/_metadata.py
CHANGED
siliconcompiler/apps/__init__.py
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from siliconcompiler.apps import sc_dashboard
|
|
2
|
+
from siliconcompiler.apps import sc_install
|
|
3
|
+
from siliconcompiler.apps import sc_issue
|
|
4
|
+
from siliconcompiler.apps import sc_remote
|
|
5
|
+
from siliconcompiler.apps import sc_server
|
|
6
|
+
from siliconcompiler.apps import sc_show
|
|
7
|
+
from siliconcompiler.apps import sc
|
|
8
|
+
from siliconcompiler.apps import smake
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_apps():
|
|
12
|
+
'''
|
|
13
|
+
Returns a dict of builtin apps
|
|
14
|
+
'''
|
|
15
|
+
return {
|
|
16
|
+
module.__name__.split(".")[-1]: module for module in (
|
|
17
|
+
sc_dashboard,
|
|
18
|
+
sc_install,
|
|
19
|
+
sc_issue,
|
|
20
|
+
sc_remote,
|
|
21
|
+
sc_server,
|
|
22
|
+
sc_show,
|
|
23
|
+
sc,
|
|
24
|
+
smake
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -126,7 +126,7 @@ def _recommended_tool_groups(tools):
|
|
|
126
126
|
groups = {
|
|
127
127
|
"asic": {"surelog", "sv2v", "yosys", "openroad", "klayout"},
|
|
128
128
|
"fpga": {"surelog", "sv2v", "yosys", "vpr"},
|
|
129
|
-
"digital-simulation": {"verilator", "icarus"},
|
|
129
|
+
"digital-simulation": {"verilator", "icarus", "gtkwave"},
|
|
130
130
|
"analog-simulation": {"xyce"}
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
# Copyright 2024 Silicon Compiler Authors. All Rights Reserved.
|
|
2
2
|
|
|
3
3
|
# Standard Modules
|
|
4
|
+
import base64
|
|
5
|
+
import io
|
|
6
|
+
import json
|
|
7
|
+
import gzip
|
|
4
8
|
import os
|
|
5
9
|
import stat
|
|
6
10
|
import sys
|
|
11
|
+
import tarfile
|
|
12
|
+
import tempfile
|
|
13
|
+
import textwrap
|
|
14
|
+
|
|
15
|
+
from datetime import datetime
|
|
7
16
|
|
|
8
17
|
import siliconcompiler
|
|
9
18
|
from siliconcompiler.apps._common import UNSET_DESIGN
|
|
@@ -11,6 +20,26 @@ from siliconcompiler import SiliconCompilerError
|
|
|
11
20
|
from siliconcompiler import utils
|
|
12
21
|
|
|
13
22
|
|
|
23
|
+
def make_bytes(data):
|
|
24
|
+
if isinstance(data, bytes):
|
|
25
|
+
return data
|
|
26
|
+
return data.encode('utf-8')
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def compress(data):
|
|
30
|
+
return gzip.compress(make_bytes(data))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def convert_base64(data):
|
|
34
|
+
return base64.b64encode(make_bytes(data))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def wrap_text(data):
|
|
38
|
+
if isinstance(data, bytes):
|
|
39
|
+
data = data.decode('utf-8')
|
|
40
|
+
return textwrap.wrap(data)
|
|
41
|
+
|
|
42
|
+
|
|
14
43
|
###########################
|
|
15
44
|
def main():
|
|
16
45
|
progname = "summarize"
|
|
@@ -25,9 +54,10 @@ def main():
|
|
|
25
54
|
|
|
26
55
|
# Read command-line inputs and generate Chip objects to run the flow on.
|
|
27
56
|
try:
|
|
28
|
-
|
|
29
|
-
'metavar': '<
|
|
30
|
-
'help': '
|
|
57
|
+
file_arg = {
|
|
58
|
+
'metavar': '<file>',
|
|
59
|
+
'help': 'Path to generate replay file to.',
|
|
60
|
+
'default': 'replay.sh',
|
|
31
61
|
'sc_print': True
|
|
32
62
|
}
|
|
33
63
|
args = chip.create_cmdline(
|
|
@@ -37,7 +67,7 @@ def main():
|
|
|
37
67
|
'-jobname',
|
|
38
68
|
'-loglevel'],
|
|
39
69
|
additional_args={
|
|
40
|
-
'-
|
|
70
|
+
'-file': file_arg
|
|
41
71
|
})
|
|
42
72
|
except SiliconCompilerError:
|
|
43
73
|
return 1
|
|
@@ -93,40 +123,68 @@ def main():
|
|
|
93
123
|
for tool, version in tools.items():
|
|
94
124
|
print(f" {os.path.basename(tool):<{tool_len}}: {', '.join(version)}")
|
|
95
125
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
path = os.path.abspath(args['file'])
|
|
127
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
128
|
+
|
|
129
|
+
starttimes = set()
|
|
130
|
+
for starttime, step, index in chip.schema._getvals('history', jobname, 'record', 'starttime'):
|
|
131
|
+
starttimes.add(datetime.strptime(starttime, '%Y-%m-%d %H:%M:%S'))
|
|
132
|
+
starttime = min(starttimes).strftime('%Y-%m-%d %H:%M:%S')
|
|
133
|
+
|
|
134
|
+
with io.StringIO() as fd:
|
|
135
|
+
fd.write(utils.get_file_template('replay/requirements.txt').render(
|
|
136
|
+
design=chip.design,
|
|
137
|
+
jobname=jobname,
|
|
138
|
+
date=starttime,
|
|
139
|
+
pkgs=pythonpackages
|
|
140
|
+
))
|
|
141
|
+
fd.flush()
|
|
142
|
+
requirements_file = fd.getvalue()
|
|
143
|
+
|
|
144
|
+
with tempfile.TemporaryDirectory() as collect:
|
|
145
|
+
chip.collect(directory=collect, verbose=True, exclude_packages=['siliconcompiler'])
|
|
146
|
+
|
|
147
|
+
with io.BytesIO() as fd:
|
|
148
|
+
with tarfile.open(fileobj=fd, mode='w:gz') as tar:
|
|
149
|
+
tar.add(collect, arcname='')
|
|
150
|
+
|
|
151
|
+
fd.flush()
|
|
152
|
+
collect_files = convert_base64(fd.getvalue())
|
|
153
|
+
|
|
154
|
+
with io.StringIO() as fd:
|
|
155
|
+
fd.write(utils.get_file_template('replay/replay.py.j2').render(
|
|
156
|
+
design=chip.design,
|
|
157
|
+
jobname=jobname,
|
|
158
|
+
date=starttime,
|
|
159
|
+
src_file=wrap_text(collect_files),
|
|
160
|
+
tool_versions=sorted(tool_versions)
|
|
161
|
+
))
|
|
162
|
+
fd.flush()
|
|
163
|
+
script = convert_base64(compress(fd.getvalue()))
|
|
164
|
+
|
|
165
|
+
manifest = convert_base64(compress(json.dumps(chip.schema.cfg, indent=2)))
|
|
166
|
+
|
|
167
|
+
tool_info = []
|
|
168
|
+
for tool, version in tools.items():
|
|
169
|
+
tool_info.append(f"{os.path.basename(tool):<{tool_len}}: {', '.join(version)}")
|
|
170
|
+
|
|
171
|
+
description = f"Replay for {chip.design} / {jobname}\nRun on: {starttime}"
|
|
172
|
+
|
|
173
|
+
with open(path, 'w', encoding='utf-8') as wf:
|
|
174
|
+
wf.write(utils.get_file_template('replay/setup.sh').render(
|
|
175
|
+
design=chip.design,
|
|
176
|
+
jobname=jobname,
|
|
177
|
+
date=starttime,
|
|
178
|
+
description=description,
|
|
179
|
+
pythonversion=pythonversion,
|
|
180
|
+
requirements=requirements_file.splitlines(),
|
|
181
|
+
script=wrap_text(script),
|
|
182
|
+
manifest=wrap_text(manifest),
|
|
183
|
+
tools=tool_info
|
|
184
|
+
))
|
|
185
|
+
|
|
186
|
+
permissions = stat.S_IMODE(os.lstat(path).st_mode)
|
|
187
|
+
os.chmod(path, permissions | stat.S_IXUSR)
|
|
130
188
|
|
|
131
189
|
return 0
|
|
132
190
|
|
siliconcompiler/core.py
CHANGED
|
@@ -255,8 +255,13 @@ class Chip:
|
|
|
255
255
|
log_format.append(f'{utils.truncate_text(step, max_step_len): <{max_step_len}}')
|
|
256
256
|
log_format.append(f'{utils.truncate_text(index, max_step_len): >{max_index_len}}')
|
|
257
257
|
|
|
258
|
+
log_formatprefix = "| "
|
|
259
|
+
if loglevel == "quiet":
|
|
260
|
+
log_format = []
|
|
261
|
+
log_formatprefix = ""
|
|
262
|
+
|
|
258
263
|
log_format.append('%(message)s')
|
|
259
|
-
logformat =
|
|
264
|
+
logformat = log_formatprefix + ' | '.join(log_format)
|
|
260
265
|
|
|
261
266
|
if not self.logger.hasHandlers():
|
|
262
267
|
stream_handler = logging.StreamHandler(stream=sys.stdout)
|
|
@@ -402,19 +407,24 @@ class Chip:
|
|
|
402
407
|
if extra_params is not None and "target" in extra_params:
|
|
403
408
|
if extra_params["target"]:
|
|
404
409
|
# running target command
|
|
405
|
-
# Search order
|
|
410
|
+
# Search order target plugins -> "{name}"
|
|
406
411
|
modules = []
|
|
407
412
|
module = extra_params["target"]
|
|
408
|
-
for
|
|
409
|
-
|
|
410
|
-
if
|
|
411
|
-
modules.append(
|
|
413
|
+
for plugin in utils.get_plugins('target'):
|
|
414
|
+
plugin_targets = plugin()
|
|
415
|
+
if module in plugin_targets:
|
|
416
|
+
modules.append(plugin_targets[module])
|
|
417
|
+
|
|
418
|
+
mod = self._load_module(module)
|
|
419
|
+
if mod:
|
|
420
|
+
modules.append(mod)
|
|
412
421
|
|
|
413
422
|
if len(modules) == 0:
|
|
414
423
|
raise SiliconCompilerError(f'Could not find target {module}', chip=self)
|
|
415
424
|
|
|
416
|
-
|
|
417
|
-
|
|
425
|
+
target = modules[0]
|
|
426
|
+
self.use(target)
|
|
427
|
+
extra_params["target"] = target.__name__
|
|
418
428
|
|
|
419
429
|
if extra_params is not None and "use" in extra_params:
|
|
420
430
|
if extra_params["use"]:
|
|
@@ -490,6 +500,9 @@ class Chip:
|
|
|
490
500
|
'dependency-caching-rebase')
|
|
491
501
|
"""
|
|
492
502
|
|
|
503
|
+
if os.path.isfile(path):
|
|
504
|
+
path = os.path.dirname(os.path.abspath(path))
|
|
505
|
+
|
|
493
506
|
preset_path = self.get('package', 'source', name, 'path')
|
|
494
507
|
preset_ref = self.get('package', 'source', name, 'ref')
|
|
495
508
|
if preset_path and preset_path != path or preset_ref and preset_ref != ref:
|
|
@@ -975,7 +988,7 @@ class Chip:
|
|
|
975
988
|
self.logger.debug(f'Setting {keypath} to {value}')
|
|
976
989
|
|
|
977
990
|
# Special case to ensure loglevel is updated ASAP
|
|
978
|
-
if keypath ==
|
|
991
|
+
if tuple(keypath) == ('option', 'loglevel') and field == 'value' and \
|
|
979
992
|
step == self.get('arg', 'step') and index == self.get('arg', 'index'):
|
|
980
993
|
self.logger.setLevel(schema_utils.translate_loglevel(value))
|
|
981
994
|
|
|
@@ -1074,6 +1087,54 @@ class Chip:
|
|
|
1074
1087
|
except (ValueError, TypeError) as e:
|
|
1075
1088
|
self.error(str(e))
|
|
1076
1089
|
|
|
1090
|
+
def import_flist(self, filename, package=None):
|
|
1091
|
+
'''
|
|
1092
|
+
Add input files, include directories, and defines from an flist
|
|
1093
|
+
|
|
1094
|
+
Args:
|
|
1095
|
+
filename (path): Path to flist file
|
|
1096
|
+
package (str): name of package
|
|
1097
|
+
'''
|
|
1098
|
+
|
|
1099
|
+
if package:
|
|
1100
|
+
filename = os.path.join(sc_package.path(self, package), filename)
|
|
1101
|
+
|
|
1102
|
+
if not os.path.isfile(filename):
|
|
1103
|
+
raise FileNotFoundError(filename)
|
|
1104
|
+
|
|
1105
|
+
package_name = f'flist-{os.path.basename(filename)}'
|
|
1106
|
+
package_dir = os.path.dirname(os.path.abspath(filename))
|
|
1107
|
+
|
|
1108
|
+
def __make_path(rel, path):
|
|
1109
|
+
path = utils._resolve_env_vars(self, path)
|
|
1110
|
+
if os.path.isabs(path):
|
|
1111
|
+
if path.startswith(rel):
|
|
1112
|
+
return os.path.relpath(path, rel), package_name
|
|
1113
|
+
else:
|
|
1114
|
+
return path, None
|
|
1115
|
+
return path, package_name
|
|
1116
|
+
|
|
1117
|
+
self.register_source(
|
|
1118
|
+
package_name,
|
|
1119
|
+
path=package_dir)
|
|
1120
|
+
with utils.sc_open(filename) as f:
|
|
1121
|
+
for line in f:
|
|
1122
|
+
line = line.strip()
|
|
1123
|
+
if not line:
|
|
1124
|
+
continue
|
|
1125
|
+
if line.startswith("//"):
|
|
1126
|
+
continue
|
|
1127
|
+
if line.startswith("+incdir+"):
|
|
1128
|
+
line = line[8:]
|
|
1129
|
+
path, package = __make_path(package_dir, line)
|
|
1130
|
+
self.add('option', 'idir', path, package=package)
|
|
1131
|
+
elif line.startswith("+define+"):
|
|
1132
|
+
line = line[8:]
|
|
1133
|
+
self.add('option', 'define', line)
|
|
1134
|
+
else:
|
|
1135
|
+
path, package = __make_path(package_dir, line)
|
|
1136
|
+
self.input(path, package=package)
|
|
1137
|
+
|
|
1077
1138
|
###########################################################################
|
|
1078
1139
|
def input(self, filename, fileset=None, filetype=None, iomap=None,
|
|
1079
1140
|
step=None, index=None, package=None):
|
|
@@ -2384,7 +2445,7 @@ class Chip:
|
|
|
2384
2445
|
swap('library', lib, 'option', 'library')
|
|
2385
2446
|
|
|
2386
2447
|
########################################################################
|
|
2387
|
-
def collect(self, directory=None, verbose=True, whitelist=None):
|
|
2448
|
+
def collect(self, directory=None, verbose=True, whitelist=None, exclude_packages=None):
|
|
2388
2449
|
'''
|
|
2389
2450
|
Collects files found in the configuration dictionary and places
|
|
2390
2451
|
them in inputs/. The function only copies in files that have the 'copy'
|
|
@@ -2402,6 +2463,8 @@ class Chip:
|
|
|
2402
2463
|
whitelist (list[path]): List of directories that are allowed to be
|
|
2403
2464
|
collected. If a directory is is found that is not on this list
|
|
2404
2465
|
a RuntimeError will be raised.
|
|
2466
|
+
package_filter (list[str]): List of packages to exclude from
|
|
2467
|
+
collection.
|
|
2405
2468
|
'''
|
|
2406
2469
|
|
|
2407
2470
|
if not directory:
|
|
@@ -2414,6 +2477,9 @@ class Chip:
|
|
|
2414
2477
|
if verbose:
|
|
2415
2478
|
self.logger.info('Collecting input sources')
|
|
2416
2479
|
|
|
2480
|
+
if not exclude_packages:
|
|
2481
|
+
exclude_packages = []
|
|
2482
|
+
|
|
2417
2483
|
dirs = {}
|
|
2418
2484
|
files = {}
|
|
2419
2485
|
|
|
@@ -2453,6 +2519,8 @@ class Chip:
|
|
|
2453
2519
|
if not package:
|
|
2454
2520
|
# Ensure package is an empty string
|
|
2455
2521
|
package = ''
|
|
2522
|
+
if package in exclude_packages:
|
|
2523
|
+
continue
|
|
2456
2524
|
if is_dir:
|
|
2457
2525
|
dirs[(package, path)] = abspath
|
|
2458
2526
|
else:
|
|
@@ -3135,6 +3203,7 @@ class Chip:
|
|
|
3135
3203
|
sc_step = self.get('arg', 'step')
|
|
3136
3204
|
sc_index = self.get('arg', 'index')
|
|
3137
3205
|
sc_job = self.get('option', 'jobname')
|
|
3206
|
+
flow = self.get('option', 'flow')
|
|
3138
3207
|
|
|
3139
3208
|
has_filename = filename is not None
|
|
3140
3209
|
# Finding last layout if no argument specified
|
|
@@ -3145,14 +3214,15 @@ class Chip:
|
|
|
3145
3214
|
if sc_step and sc_index:
|
|
3146
3215
|
search_nodes.append((sc_step, sc_index))
|
|
3147
3216
|
elif sc_step:
|
|
3148
|
-
for check_step, check_index in nodes_to_execute(self,
|
|
3217
|
+
for check_step, check_index in nodes_to_execute(self, flow):
|
|
3149
3218
|
if sc_step == check_step:
|
|
3150
3219
|
search_nodes.append((check_step, check_index))
|
|
3151
3220
|
else:
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3221
|
+
if flow is not None:
|
|
3222
|
+
for nodes in _get_flowgraph_execution_order(self,
|
|
3223
|
+
flow,
|
|
3224
|
+
reverse=True):
|
|
3225
|
+
search_nodes.extend(nodes)
|
|
3156
3226
|
|
|
3157
3227
|
for ext in self._showtools.keys():
|
|
3158
3228
|
if extension and extension != ext:
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from siliconcompiler.flows import asicflow
|
|
2
|
+
from siliconcompiler.flows import asictopflow
|
|
3
|
+
from siliconcompiler.flows import drcflow
|
|
4
|
+
from siliconcompiler.flows import dvflow
|
|
5
|
+
from siliconcompiler.flows import fpgaflow
|
|
6
|
+
from siliconcompiler.flows import generate_openroad_rcx
|
|
7
|
+
from siliconcompiler.flows import interposerflow
|
|
8
|
+
from siliconcompiler.flows import lintflow
|
|
9
|
+
from siliconcompiler.flows import screenshotflow
|
|
10
|
+
from siliconcompiler.flows import showflow
|
|
11
|
+
from siliconcompiler.flows import signoffflow
|
|
12
|
+
from siliconcompiler.flows import synflow
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_flows():
|
|
16
|
+
'''
|
|
17
|
+
Returns a dict of builtin flows
|
|
18
|
+
'''
|
|
19
|
+
return {
|
|
20
|
+
module.__name__.split(".")[-1]: module for module in (
|
|
21
|
+
asicflow,
|
|
22
|
+
asictopflow,
|
|
23
|
+
drcflow,
|
|
24
|
+
dvflow,
|
|
25
|
+
fpgaflow,
|
|
26
|
+
generate_openroad_rcx,
|
|
27
|
+
interposerflow,
|
|
28
|
+
lintflow,
|
|
29
|
+
screenshotflow,
|
|
30
|
+
showflow,
|
|
31
|
+
signoffflow,
|
|
32
|
+
synflow
|
|
33
|
+
)
|
|
34
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import siliconcompiler
|
|
2
2
|
from siliconcompiler import SiliconCompilerError
|
|
3
|
-
from siliconcompiler.targets import freepdk45_demo
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
############################################################################
|
|
7
6
|
# DOCS
|
|
8
7
|
############################################################################
|
|
9
8
|
def make_docs(chip):
|
|
9
|
+
from siliconcompiler.targets import freepdk45_demo
|
|
10
10
|
chip.use(freepdk45_demo)
|
|
11
11
|
return setup(filetype='gds', showtools=chip._showtools, np=3)
|
|
12
12
|
|
siliconcompiler/libs/__init__.py
CHANGED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
class Optimizer:
|
|
2
|
+
def __init__(self, chip):
|
|
3
|
+
self._chip = chip
|
|
4
|
+
|
|
5
|
+
self._parameters = {}
|
|
6
|
+
self._goals = {}
|
|
7
|
+
self._assertions = {}
|
|
8
|
+
|
|
9
|
+
self.__results = []
|
|
10
|
+
|
|
11
|
+
def __generate_print_name(self, key, step, index):
|
|
12
|
+
name = f'[{",".join(key)}]'
|
|
13
|
+
|
|
14
|
+
node_name = None
|
|
15
|
+
if step is not None:
|
|
16
|
+
node_name = step
|
|
17
|
+
|
|
18
|
+
if index is not None:
|
|
19
|
+
node_name += f'{index}'
|
|
20
|
+
|
|
21
|
+
if node_name:
|
|
22
|
+
name += f' ({node_name})'
|
|
23
|
+
|
|
24
|
+
return name
|
|
25
|
+
|
|
26
|
+
def __generate_param_name(self, key, step, index):
|
|
27
|
+
name = ",".join(key)
|
|
28
|
+
|
|
29
|
+
if step is not None:
|
|
30
|
+
name += f'-step-{step}'
|
|
31
|
+
|
|
32
|
+
if index is not None:
|
|
33
|
+
name += f'-index-{index}'
|
|
34
|
+
|
|
35
|
+
return name
|
|
36
|
+
|
|
37
|
+
def add_parameter(self, key, values, value_type=None, step=None, index=None):
|
|
38
|
+
if value_type is None:
|
|
39
|
+
value_type = self._chip.get(*key, field='type')
|
|
40
|
+
if value_type.startswith('['):
|
|
41
|
+
value_type = value_type[1:-1]
|
|
42
|
+
elif value_type.startswith('('):
|
|
43
|
+
value_type = value_type[1:-1].split(",")
|
|
44
|
+
value_type = [value.strip() for value in value_type]
|
|
45
|
+
if not all([value == value_type[0] for value in value_type]):
|
|
46
|
+
raise ValueError("Cannot support unequal tuples")
|
|
47
|
+
value_type = value_type[0]
|
|
48
|
+
|
|
49
|
+
if value_type not in ('float', 'int', 'bool', 'enum', 'str'):
|
|
50
|
+
raise ValueError(f"{value_type} is not supported")
|
|
51
|
+
|
|
52
|
+
if value_type in ('float', 'int'):
|
|
53
|
+
if 'max' not in values:
|
|
54
|
+
raise ValueError("value must have a max key")
|
|
55
|
+
if 'min' not in values:
|
|
56
|
+
raise ValueError("value must have a min key")
|
|
57
|
+
values = [values["min"], values["max"]]
|
|
58
|
+
elif value_type in ('enum', 'str', 'bool'):
|
|
59
|
+
if not isinstance(values, (tuple, list, set)):
|
|
60
|
+
raise ValueError("value must be a list")
|
|
61
|
+
if value_type == 'str':
|
|
62
|
+
value_type = 'enum'
|
|
63
|
+
|
|
64
|
+
if value_type == 'bool' and not values:
|
|
65
|
+
values = [True, False]
|
|
66
|
+
|
|
67
|
+
self._parameters["param-" + self.__generate_param_name(key, step, index)] = {
|
|
68
|
+
"print": self.__generate_print_name(key, step, index),
|
|
69
|
+
"key": tuple(key),
|
|
70
|
+
"type": value_type,
|
|
71
|
+
"values": tuple(values),
|
|
72
|
+
"step": step,
|
|
73
|
+
"index": index
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def _set_parameter(self, parameter, value, chip, flow_prefix=None):
|
|
77
|
+
param_entry = self._parameters[parameter]
|
|
78
|
+
|
|
79
|
+
self._chip.logger.info(f' Setting {param_entry["print"]} = {value}')
|
|
80
|
+
if param_entry["step"]:
|
|
81
|
+
if not flow_prefix:
|
|
82
|
+
flow_prefix = ""
|
|
83
|
+
step = f'{flow_prefix}{param_entry["step"]}'
|
|
84
|
+
else:
|
|
85
|
+
step = param_entry["step"]
|
|
86
|
+
|
|
87
|
+
key_type = chip.get(*param_entry["key"], field='type')
|
|
88
|
+
if key_type[0] == "(":
|
|
89
|
+
key_type = key_type[1:-1].split(",")
|
|
90
|
+
value = len(key_type) * [value]
|
|
91
|
+
|
|
92
|
+
chip.set(
|
|
93
|
+
*param_entry["key"],
|
|
94
|
+
value,
|
|
95
|
+
step=step,
|
|
96
|
+
index=param_entry["index"])
|
|
97
|
+
|
|
98
|
+
def add_assertion(self, key, criteria, step=None, index=None):
|
|
99
|
+
if not callable(criteria):
|
|
100
|
+
raise ValueError('criteria must be a function')
|
|
101
|
+
|
|
102
|
+
if not step:
|
|
103
|
+
raise ValueError('step is required')
|
|
104
|
+
|
|
105
|
+
if not index:
|
|
106
|
+
raise ValueError('index is required')
|
|
107
|
+
|
|
108
|
+
self._assertions["assert-" + self.__generate_param_name(key, step, index)] = {
|
|
109
|
+
"print": self.__generate_print_name(key, step, index),
|
|
110
|
+
"key": tuple(key),
|
|
111
|
+
"criteria": criteria,
|
|
112
|
+
"step": step,
|
|
113
|
+
"index": index
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
def _check_assertions(self, chip, step_prefix):
|
|
117
|
+
if not step_prefix:
|
|
118
|
+
step_prefix = ""
|
|
119
|
+
|
|
120
|
+
for info in self._assertions.values():
|
|
121
|
+
value = chip.get(
|
|
122
|
+
*info["key"],
|
|
123
|
+
step=f'{step_prefix}{info["step"]}',
|
|
124
|
+
index=info["index"])
|
|
125
|
+
if not info["criteria"](value):
|
|
126
|
+
self._chip.logger.error(f"Failed to meet assertion: {info['print']} with {value}")
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
return True
|
|
130
|
+
|
|
131
|
+
def add_goal(self, key, goal, stop_goal=None, step=None, index=None):
|
|
132
|
+
if goal not in ('min', 'max'):
|
|
133
|
+
raise ValueError(f"{goal} is not supported")
|
|
134
|
+
|
|
135
|
+
if not step:
|
|
136
|
+
raise ValueError('step is required')
|
|
137
|
+
|
|
138
|
+
if not index:
|
|
139
|
+
raise ValueError('index is required')
|
|
140
|
+
|
|
141
|
+
self._goals["goal-" + self.__generate_param_name(key, step, index)] = {
|
|
142
|
+
"print": self.__generate_print_name(key, step, index),
|
|
143
|
+
"key": tuple(key),
|
|
144
|
+
"goal": goal,
|
|
145
|
+
"stop": stop_goal,
|
|
146
|
+
"step": step,
|
|
147
|
+
"index": index
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
def _check_stop_goal(self, measurements):
|
|
151
|
+
cont = []
|
|
152
|
+
|
|
153
|
+
for param, info in self._goals.items():
|
|
154
|
+
if info["stop"] is None:
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
if param not in measurements:
|
|
158
|
+
cont.append(False)
|
|
159
|
+
continue
|
|
160
|
+
|
|
161
|
+
if info["goal"] == "min":
|
|
162
|
+
if measurements[param] <= info["stop"]:
|
|
163
|
+
cont.append(True)
|
|
164
|
+
elif info["goal"] == "max":
|
|
165
|
+
if measurements[param] >= info["stop"]:
|
|
166
|
+
cont.append(True)
|
|
167
|
+
|
|
168
|
+
if not cont:
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
return all(cont)
|
|
172
|
+
|
|
173
|
+
def run(self, experiments=None, parallel=None):
|
|
174
|
+
raise NotImplementedError
|
|
175
|
+
|
|
176
|
+
def _clear_results(self):
|
|
177
|
+
self.__results.clear()
|
|
178
|
+
|
|
179
|
+
def _add_result(self, parameters, measurements):
|
|
180
|
+
self.__results.append({
|
|
181
|
+
"parameters": parameters,
|
|
182
|
+
"measurements": measurements
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
def report(self, count=None):
|
|
186
|
+
for n, result in enumerate(self.__results):
|
|
187
|
+
if count and n >= count:
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
self._chip.logger.info(f"Result {n+1} / {len(self.__results)}:")
|
|
191
|
+
self._chip.logger.info(" Parameters:")
|
|
192
|
+
for param_name, param_key in result["parameters"].items():
|
|
193
|
+
param_print = self._parameters[param_name]['print']
|
|
194
|
+
self._chip.logger.info(f" {param_print} = {param_key}")
|
|
195
|
+
|
|
196
|
+
self._chip.logger.info(" Measurements:")
|
|
197
|
+
for meas_name, meas_key in result["measurements"].metrics.items():
|
|
198
|
+
goal_print = self._goals[meas_name]['print']
|
|
199
|
+
self._chip.logger.info(f" {goal_print} = {meas_key.value}")
|