siliconcompiler 0.28.4__py3-none-any.whl → 0.28.6__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/_common.py +88 -56
- siliconcompiler/apps/sc.py +33 -14
- siliconcompiler/apps/sc_dashboard.py +16 -9
- siliconcompiler/apps/sc_show.py +17 -15
- siliconcompiler/apps/utils/summarize.py +47 -0
- siliconcompiler/core.py +20 -12
- siliconcompiler/flows/drcflow.py +13 -0
- siliconcompiler/flows/interposerflow.py +17 -0
- siliconcompiler/libs/interposer.py +8 -0
- siliconcompiler/pdks/interposer.py +8 -0
- siliconcompiler/remote/schema.py +11 -1
- siliconcompiler/remote/server.py +7 -2
- siliconcompiler/report/dashboard/__init__.py +10 -3
- siliconcompiler/scheduler/__init__.py +93 -0
- siliconcompiler/schema/schema_cfg.py +15 -3
- siliconcompiler/schema/schema_obj.py +51 -1
- siliconcompiler/targets/interposer_demo.py +56 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +2 -0
- siliconcompiler/tools/klayout/export.py +7 -4
- siliconcompiler/tools/klayout/klayout_export.py +3 -0
- siliconcompiler/tools/klayout/klayout_utils.py +8 -2
- siliconcompiler/tools/openroad/metrics.py +44 -0
- siliconcompiler/tools/openroad/openroad.py +3 -0
- siliconcompiler/tools/openroad/rdlroute.py +97 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +20 -22
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +0 -169
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +184 -0
- siliconcompiler/tools/openroad/scripts/sc_report.tcl +170 -0
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +11 -1
- siliconcompiler/tools/xyce/__init__.py +1 -1
- siliconcompiler/toolscripts/_tools.json +3 -4
- siliconcompiler/toolscripts/rhel8/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/rhel9/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +5 -5
- siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +2 -2
- siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +2 -2
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/METADATA +14 -12
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/RECORD +43 -33
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.6.dist-info}/top_level.txt +0 -0
|
@@ -688,7 +688,9 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
|
|
|
688
688
|
runtime_options = getattr(chip._get_tool_module(step, index), 'runtime_options', None)
|
|
689
689
|
if runtime_options:
|
|
690
690
|
try:
|
|
691
|
+
chip.schema._start_record_access()
|
|
691
692
|
cmdlist.extend(parse_options(runtime_options(chip)))
|
|
693
|
+
chip.schema._stop_record_access()
|
|
692
694
|
except Exception as e:
|
|
693
695
|
chip.logger.error(f'Failed to get runtime options for {tool}/{task}')
|
|
694
696
|
raise e
|
|
@@ -983,7 +985,9 @@ def _post_process(chip, step, index):
|
|
|
983
985
|
func = getattr(chip._get_task_module(step, index, flow=flow), 'post_process', None)
|
|
984
986
|
if func:
|
|
985
987
|
try:
|
|
988
|
+
chip.schema._start_record_access()
|
|
986
989
|
func(chip)
|
|
990
|
+
chip.schema._stop_record_access()
|
|
987
991
|
except Exception as e:
|
|
988
992
|
chip.logger.error(f'Failed to run post-process for {tool}/{task}.')
|
|
989
993
|
print_traceback(chip, e)
|
|
@@ -1076,7 +1080,9 @@ def _pre_process(chip, step, index):
|
|
|
1076
1080
|
func = getattr(chip._get_task_module(step, index, flow=flow), 'pre_process', None)
|
|
1077
1081
|
if func:
|
|
1078
1082
|
try:
|
|
1083
|
+
chip.schema._start_record_access()
|
|
1079
1084
|
func(chip)
|
|
1085
|
+
chip.schema._stop_record_access()
|
|
1080
1086
|
except Exception as e:
|
|
1081
1087
|
chip.logger.error(f"Pre-processing failed for '{tool}/{task}'.")
|
|
1082
1088
|
raise e
|
|
@@ -1088,6 +1094,8 @@ def _pre_process(chip, step, index):
|
|
|
1088
1094
|
def _set_env_vars(chip, step, index):
|
|
1089
1095
|
flow = chip.get('option', 'flow')
|
|
1090
1096
|
tool, task = get_tool_task(chip, step, index, flow)
|
|
1097
|
+
|
|
1098
|
+
chip.schema._start_record_access()
|
|
1091
1099
|
# License file configuration.
|
|
1092
1100
|
for item in chip.getkeys('tool', tool, 'licenseserver'):
|
|
1093
1101
|
license_file = chip.get('tool', tool, 'licenseserver', item, step=step, index=index)
|
|
@@ -1100,6 +1108,8 @@ def _set_env_vars(chip, step, index):
|
|
|
1100
1108
|
if val:
|
|
1101
1109
|
os.environ[item] = val
|
|
1102
1110
|
|
|
1111
|
+
chip.schema._stop_record_access()
|
|
1112
|
+
|
|
1103
1113
|
|
|
1104
1114
|
def _check_tool_version(chip, step, index, run_func=None):
|
|
1105
1115
|
'''
|
|
@@ -1191,6 +1201,9 @@ def _hash_files(chip, step, index, setup=False):
|
|
|
1191
1201
|
|
|
1192
1202
|
|
|
1193
1203
|
def _finalizenode(chip, step, index, replay):
|
|
1204
|
+
if chip.schema._do_record_access():
|
|
1205
|
+
assert_required_accesses(chip, step, index)
|
|
1206
|
+
|
|
1194
1207
|
flow = chip.get('option', 'flow')
|
|
1195
1208
|
tool, task = get_tool_task(chip, step, index, flow)
|
|
1196
1209
|
quiet = (
|
|
@@ -1286,6 +1299,86 @@ def assert_output_files(chip, step, index):
|
|
|
1286
1299
|
chip=chip)
|
|
1287
1300
|
|
|
1288
1301
|
|
|
1302
|
+
def assert_required_accesses(chip, step, index):
|
|
1303
|
+
flow = chip.get('option', 'flow')
|
|
1304
|
+
jobname = chip.get('option', 'jobname')
|
|
1305
|
+
tool, task = get_tool_task(chip, step, index, flow)
|
|
1306
|
+
|
|
1307
|
+
if tool == 'builtin':
|
|
1308
|
+
return
|
|
1309
|
+
|
|
1310
|
+
gets = chip.schema._get_record_access()
|
|
1311
|
+
logfile = os.path.join(
|
|
1312
|
+
chip.getworkdir(jobname=jobname, step=step, index=index),
|
|
1313
|
+
f'{step}.log')
|
|
1314
|
+
|
|
1315
|
+
with sc_open(logfile) as f:
|
|
1316
|
+
for line in f:
|
|
1317
|
+
if line.startswith(Schema._RECORD_ACCESS_IDENTIFIER):
|
|
1318
|
+
key = line[len(Schema._RECORD_ACCESS_IDENTIFIER):].strip().split(',')
|
|
1319
|
+
if chip.valid(*key, check_complete=True):
|
|
1320
|
+
gets.add(tuple(key))
|
|
1321
|
+
|
|
1322
|
+
def get_value(*key):
|
|
1323
|
+
if chip.get(*key, field='pernode') == 'never':
|
|
1324
|
+
return chip.get(*key)
|
|
1325
|
+
else:
|
|
1326
|
+
return chip.get(*key, step=step, index=index)
|
|
1327
|
+
|
|
1328
|
+
getkeys = set()
|
|
1329
|
+
# Remove keys with empty values
|
|
1330
|
+
for key in set(sorted(gets)):
|
|
1331
|
+
if get_value(*key):
|
|
1332
|
+
getkeys.add(key)
|
|
1333
|
+
|
|
1334
|
+
# Remove keys that dont matter
|
|
1335
|
+
exempt = [
|
|
1336
|
+
('design',),
|
|
1337
|
+
('arg', 'step'), ('arg', 'index'),
|
|
1338
|
+
('option', 'jobname'), ('option', 'flow'), ('option', 'strict'), ('option', 'builddir'),
|
|
1339
|
+
('option', 'quiet'),
|
|
1340
|
+
('tool', tool, 'exe'),
|
|
1341
|
+
('tool', tool, 'task', task, 'require'),
|
|
1342
|
+
('tool', tool, 'task', task, 'threads'),
|
|
1343
|
+
('flowgraph', flow, step, index, 'tool'), ('flowgraph', flow, step, index, 'task'),
|
|
1344
|
+
('flowgraph', flow, step, index, 'taskmodule')]
|
|
1345
|
+
for key in chip.getkeys('metric'):
|
|
1346
|
+
exempt.append(('metric', key))
|
|
1347
|
+
for key in chip.getkeys('tool', tool, 'task', task, 'report'):
|
|
1348
|
+
exempt.append(('tool', tool, 'task', task, 'report', key))
|
|
1349
|
+
|
|
1350
|
+
# Get exempted keys from task
|
|
1351
|
+
func = getattr(chip._get_task_module(step, index, flow=flow), 'exempt_keys', None)
|
|
1352
|
+
if func:
|
|
1353
|
+
# No need for try / except since this must work properly
|
|
1354
|
+
exempt.extend(func(chip))
|
|
1355
|
+
|
|
1356
|
+
required = set(
|
|
1357
|
+
[tuple(key.split(',')) for key in chip.get('tool', tool, 'task', task, 'require',
|
|
1358
|
+
step=step, index=index)])
|
|
1359
|
+
|
|
1360
|
+
for key in set(exempt):
|
|
1361
|
+
if key in getkeys:
|
|
1362
|
+
getkeys.remove(key)
|
|
1363
|
+
if key in required:
|
|
1364
|
+
required.remove(key)
|
|
1365
|
+
|
|
1366
|
+
excess_require = required.difference(getkeys)
|
|
1367
|
+
if True:
|
|
1368
|
+
for key in sorted(excess_require):
|
|
1369
|
+
chip.logger.error(f"{step}{index} does not require requirement: {','.join(key)}")
|
|
1370
|
+
missing_require = getkeys.difference(required)
|
|
1371
|
+
for key in sorted(missing_require):
|
|
1372
|
+
chip.logger.error(f"{step}{index} has an unexpressed requirement: "
|
|
1373
|
+
f"{','.join(key)} = {get_value(*key)}")
|
|
1374
|
+
|
|
1375
|
+
if missing_require:
|
|
1376
|
+
raise SiliconCompilerError(
|
|
1377
|
+
f'Requirements for {step}{index} does not match access list: '
|
|
1378
|
+
f'{", ".join([",".join(key) for key in sorted(missing_require)])}',
|
|
1379
|
+
chip=chip)
|
|
1380
|
+
|
|
1381
|
+
|
|
1289
1382
|
def _reset_flow_nodes(chip, flow, nodes_to_execute):
|
|
1290
1383
|
# Reset flowgraph/records/metrics by probing build directory. We need
|
|
1291
1384
|
# to set values to None for steps we may re-run so that merging
|
|
@@ -10,7 +10,7 @@ try:
|
|
|
10
10
|
except ImportError:
|
|
11
11
|
from siliconcompiler.schema.utils import trim
|
|
12
12
|
|
|
13
|
-
SCHEMA_VERSION = '0.48.
|
|
13
|
+
SCHEMA_VERSION = '0.48.4'
|
|
14
14
|
|
|
15
15
|
#############################################################################
|
|
16
16
|
# PARAM DEFINITION
|
|
@@ -1252,7 +1252,6 @@ def schema_datasheet(cfg, name='default', mode='default'):
|
|
|
1252
1252
|
# Package Description
|
|
1253
1253
|
#########################
|
|
1254
1254
|
|
|
1255
|
-
# high level description
|
|
1256
1255
|
scparam(cfg, ['datasheet', 'package', name, 'type'],
|
|
1257
1256
|
sctype='enum',
|
|
1258
1257
|
enum=['bga', 'lga', 'csp', 'qfn', 'qfp', 'sop', 'die', 'wafer'],
|
|
@@ -1263,6 +1262,16 @@ def schema_datasheet(cfg, name='default', mode='default'):
|
|
|
1263
1262
|
"api: chip.set('datasheet', 'package', 'abcd', 'type', 'bga')"],
|
|
1264
1263
|
schelp="""Package type specified on a named package basis.""")
|
|
1265
1264
|
|
|
1265
|
+
scparam(cfg, ['datasheet', 'package', name, 'footprint'],
|
|
1266
|
+
sctype='str',
|
|
1267
|
+
shorthelp="Datasheet: package footprint",
|
|
1268
|
+
switch="-datasheet_package_footprint 'name <str>'",
|
|
1269
|
+
example=[
|
|
1270
|
+
"cli: -datasheet_package_footprint 'abcd soic8'",
|
|
1271
|
+
"api: chip.set('datasheet', 'package', 'abcd', 'footprint', 'soic8')"],
|
|
1272
|
+
schelp="""Package footprint name. The name of the footprint can be a standard
|
|
1273
|
+
footprint name or a reference designator from a footprint library.""")
|
|
1274
|
+
|
|
1266
1275
|
scparam(cfg, ['datasheet', 'package', name, 'drawing'],
|
|
1267
1276
|
sctype='[file]',
|
|
1268
1277
|
shorthelp="Datasheet: package drawing",
|
|
@@ -2158,7 +2167,10 @@ def schema_metric(cfg, step='default', index='default'):
|
|
|
2158
2167
|
device families.""")
|
|
2159
2168
|
|
|
2160
2169
|
metrics = {'cellarea': 'cell area (ignoring fillers)',
|
|
2161
|
-
'totalarea': 'physical die area'
|
|
2170
|
+
'totalarea': 'physical die area',
|
|
2171
|
+
'macroarea': 'macro cell area',
|
|
2172
|
+
'padcellarea': 'io pad cell area',
|
|
2173
|
+
'stdcellarea': 'standard cell area'}
|
|
2162
2174
|
|
|
2163
2175
|
for item, val in metrics.items():
|
|
2164
2176
|
scparam(cfg, ['metric', item],
|
|
@@ -61,6 +61,8 @@ class Schema:
|
|
|
61
61
|
logger (logging.Logger): instance of the parent logger if available
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
|
+
_RECORD_ACCESS_IDENTIFIER = "SC_CFG_ACCESS_KEY"
|
|
65
|
+
|
|
64
66
|
# Special key in node dict that represents a value corresponds to a
|
|
65
67
|
# global default for all steps/indices.
|
|
66
68
|
GLOBAL_KEY = 'global'
|
|
@@ -70,6 +72,9 @@ class Schema:
|
|
|
70
72
|
if cfg is not None and manifest is not None:
|
|
71
73
|
raise ValueError('You may not specify both cfg and manifest')
|
|
72
74
|
|
|
75
|
+
# Use during testing to record calls to Schema.get
|
|
76
|
+
self._init_record_access()
|
|
77
|
+
|
|
73
78
|
self._init_logger(logger)
|
|
74
79
|
|
|
75
80
|
self._stop_journal()
|
|
@@ -256,6 +261,10 @@ class Schema:
|
|
|
256
261
|
|
|
257
262
|
See :meth:`~siliconcompiler.core.Chip.get` for detailed documentation.
|
|
258
263
|
"""
|
|
264
|
+
|
|
265
|
+
if self.__record_access["recording"]:
|
|
266
|
+
self.__record_access["record"].add(tuple(keypath))
|
|
267
|
+
|
|
259
268
|
# Prevent accidental modifications of the schema content by not passing a reference
|
|
260
269
|
return copy.copy(self.__get(*keypath, field=field, job=job, step=step, index=index))
|
|
261
270
|
|
|
@@ -1087,7 +1096,9 @@ class Schema:
|
|
|
1087
1096
|
|
|
1088
1097
|
if template:
|
|
1089
1098
|
fout.write(template.render(manifest_dict='\n'.join(tcl_set_cmds),
|
|
1090
|
-
scroot=os.path.abspath(PACKAGE_ROOT)
|
|
1099
|
+
scroot=os.path.abspath(PACKAGE_ROOT),
|
|
1100
|
+
record_access=self._do_record_access(),
|
|
1101
|
+
record_access_id=Schema._RECORD_ACCESS_IDENTIFIER))
|
|
1091
1102
|
else:
|
|
1092
1103
|
for cmd in tcl_set_cmds:
|
|
1093
1104
|
fout.write(cmd + '\n')
|
|
@@ -1305,6 +1316,45 @@ class Schema:
|
|
|
1305
1316
|
except Exception as e:
|
|
1306
1317
|
self.logger.error(f'Exception: {e}')
|
|
1307
1318
|
|
|
1319
|
+
#######################################
|
|
1320
|
+
def _do_record_access(self):
|
|
1321
|
+
'''
|
|
1322
|
+
Determine if Schema should record calls to .get
|
|
1323
|
+
'''
|
|
1324
|
+
return False
|
|
1325
|
+
|
|
1326
|
+
#######################################
|
|
1327
|
+
def _init_record_access(self):
|
|
1328
|
+
'''
|
|
1329
|
+
Initialize record access data record
|
|
1330
|
+
'''
|
|
1331
|
+
self.__record_access = {
|
|
1332
|
+
"do": self._do_record_access(),
|
|
1333
|
+
"recording": False,
|
|
1334
|
+
"record": set()
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
#######################################
|
|
1338
|
+
def _start_record_access(self):
|
|
1339
|
+
'''
|
|
1340
|
+
Start recording calls to .get
|
|
1341
|
+
'''
|
|
1342
|
+
self.__record_access["recording"] = True
|
|
1343
|
+
|
|
1344
|
+
#######################################
|
|
1345
|
+
def _stop_record_access(self):
|
|
1346
|
+
'''
|
|
1347
|
+
Stop recording calls to .get
|
|
1348
|
+
'''
|
|
1349
|
+
self.__record_access["recording"] = False
|
|
1350
|
+
|
|
1351
|
+
#######################################
|
|
1352
|
+
def _get_record_access(self):
|
|
1353
|
+
'''
|
|
1354
|
+
Return calls to record_access
|
|
1355
|
+
'''
|
|
1356
|
+
return self.__record_access["record"].copy()
|
|
1357
|
+
|
|
1308
1358
|
#######################################
|
|
1309
1359
|
def get_default(self, *keypath):
|
|
1310
1360
|
'''Returns default value of a parameter.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from siliconcompiler import Chip
|
|
2
|
+
from siliconcompiler.flows import interposerflow, drcflow
|
|
3
|
+
|
|
4
|
+
from lambdapdk import interposer
|
|
5
|
+
from lambdapdk.interposer.libs import bumps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
####################################################
|
|
9
|
+
# Target Setup
|
|
10
|
+
####################################################
|
|
11
|
+
def setup(chip):
|
|
12
|
+
'''
|
|
13
|
+
Interposer Demo Target
|
|
14
|
+
'''
|
|
15
|
+
|
|
16
|
+
# 1. Load PDK, flow, libs
|
|
17
|
+
chip.use(interposer)
|
|
18
|
+
chip.use(bumps)
|
|
19
|
+
chip.use(interposerflow)
|
|
20
|
+
chip.use(drcflow)
|
|
21
|
+
|
|
22
|
+
# 2. Set default targets
|
|
23
|
+
chip.set('option', 'flow', 'interposerflow', clobber=False)
|
|
24
|
+
chip.set('option', 'pdk', 'interposer', clobber=False)
|
|
25
|
+
chip.set('option', 'stackup', '3ML_0400', clobber=False)
|
|
26
|
+
chip.set('option', 'var', 'openroad_libtype', 'none', clobber=False)
|
|
27
|
+
chip.set('option', 'var', 'klayout_libtype', 'none', clobber=False)
|
|
28
|
+
|
|
29
|
+
# 3. Set project specific design choices
|
|
30
|
+
chip.set('asic', 'macrolib', 'interposer_bumps', clobber=False)
|
|
31
|
+
|
|
32
|
+
# 4. get project specific design choices
|
|
33
|
+
chip.set('asic', 'delaymodel', 'nldm', clobber=False)
|
|
34
|
+
|
|
35
|
+
# 5. Timing corners
|
|
36
|
+
chip.set('constraint', 'timing', 'slow', 'libcorner', 'slow', clobber=False)
|
|
37
|
+
chip.set('constraint', 'timing', 'slow', 'pexcorner', 'maximum', clobber=False)
|
|
38
|
+
chip.set('constraint', 'timing', 'slow', 'mode', 'func', clobber=False)
|
|
39
|
+
chip.set('constraint', 'timing', 'slow', 'check', ['setup', 'hold'], clobber=False)
|
|
40
|
+
|
|
41
|
+
chip.set('constraint', 'timing', 'fast', 'libcorner', 'fast', clobber=False)
|
|
42
|
+
chip.set('constraint', 'timing', 'fast', 'pexcorner', 'minimum', clobber=False)
|
|
43
|
+
chip.set('constraint', 'timing', 'fast', 'mode', 'func', clobber=False)
|
|
44
|
+
chip.set('constraint', 'timing', 'fast', 'check', ['setup', 'hold'], clobber=False)
|
|
45
|
+
|
|
46
|
+
chip.set('constraint', 'timing', 'typical', 'libcorner', 'typ', clobber=False)
|
|
47
|
+
chip.set('constraint', 'timing', 'typical', 'pexcorner', 'typical', clobber=False)
|
|
48
|
+
chip.set('constraint', 'timing', 'typical', 'mode', 'func', clobber=False)
|
|
49
|
+
chip.set('constraint', 'timing', 'typical', 'check', ['setup', 'hold'], clobber=False)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
#########################
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
target = Chip('<target>')
|
|
55
|
+
setup(target)
|
|
56
|
+
target.write_manifest('interposer_demo.json')
|
|
@@ -16,6 +16,8 @@ proc sc_cfg_get { args } {
|
|
|
16
16
|
# Refer to global sc_cfg dictionary
|
|
17
17
|
global sc_cfg
|
|
18
18
|
|
|
19
|
+
{% if record_access %}puts "{{ record_access_id }} [join $args ,]"{% endif %}
|
|
20
|
+
|
|
19
21
|
if { ![sc_cfg_exists {*}$args] } {
|
|
20
22
|
throw {FLOW KEYERROR} "key \"$args\" is not in the siliconcompiler configuration"
|
|
21
23
|
}
|
|
@@ -41,11 +41,9 @@ def setup(chip):
|
|
|
41
41
|
step=step, index=index)[0]
|
|
42
42
|
sc_stream_order = [default_stream, *[s for s in streams if s != default_stream]]
|
|
43
43
|
|
|
44
|
-
if stackup
|
|
44
|
+
if stackup:
|
|
45
45
|
macrolibs = get_libraries(chip, 'macro')
|
|
46
46
|
|
|
47
|
-
chip.add('tool', tool, 'task', task, 'require', ",".join(['asic', 'logiclib']),
|
|
48
|
-
step=step, index=index)
|
|
49
47
|
chip.add('tool', tool, 'task', task, 'require', ",".join(['option', 'stackup']),
|
|
50
48
|
step=step, index=index)
|
|
51
49
|
req_set = False
|
|
@@ -83,7 +81,12 @@ def setup(chip):
|
|
|
83
81
|
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
84
82
|
step=step, index=index)
|
|
85
83
|
else:
|
|
86
|
-
chip.error('Stackup
|
|
84
|
+
chip.error('Stackup parameter required for Klayout.')
|
|
85
|
+
|
|
86
|
+
if not targetlibs:
|
|
87
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
88
|
+
'option,var,klayout_libtype',
|
|
89
|
+
step=step, index=index)
|
|
87
90
|
|
|
88
91
|
# Input/Output requirements for default flow
|
|
89
92
|
design = chip.top()
|
|
@@ -61,6 +61,9 @@ def gds_export(design_name, in_def, in_files, out_file, tech, allow_missing, con
|
|
|
61
61
|
for cell in def_cells:
|
|
62
62
|
print(f" [INFO] DEF cell: {cell}")
|
|
63
63
|
|
|
64
|
+
if f"{design_name}_DEF_FILL" in def_cells:
|
|
65
|
+
def_cells.remove(f"{design_name}_DEF_FILL")
|
|
66
|
+
|
|
64
67
|
# Load in the gds to merge
|
|
65
68
|
print("[INFO] Merging GDS/OAS files...")
|
|
66
69
|
for fil in in_files:
|
|
@@ -31,8 +31,14 @@ def technology(design, schema):
|
|
|
31
31
|
sc_stackup = schema.get('option', 'stackup')
|
|
32
32
|
else:
|
|
33
33
|
sc_stackup = schema.get('pdk', sc_pdk, 'stackup')[0]
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
|
|
35
|
+
logiclibs = schema.get('asic', 'logiclib', step=sc_step, index=sc_index)
|
|
36
|
+
if not logiclibs:
|
|
37
|
+
sc_libtype = schema.get('option', 'var', 'klayout_libtype')[0]
|
|
38
|
+
else:
|
|
39
|
+
sc_mainlib = logiclibs[0]
|
|
40
|
+
sc_libtype = schema.get('library', sc_mainlib, 'asic', 'libarch',
|
|
41
|
+
step=sc_step, index=sc_index)
|
|
36
42
|
|
|
37
43
|
sc_libs = []
|
|
38
44
|
sc_libs += get_libraries(schema, 'logic')
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from siliconcompiler.tools.openroad.openroad import setup as setup_tool
|
|
2
|
+
from siliconcompiler.tools.openroad.openroad import build_pex_corners
|
|
3
|
+
from siliconcompiler.tools.openroad.openroad import post_process as or_post_process
|
|
4
|
+
from siliconcompiler.tools.openroad.openroad import pre_process as or_pre_process
|
|
5
|
+
from siliconcompiler.tools.openroad.openroad import _set_reports, set_pnr_inputs, set_pnr_outputs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def setup(chip):
|
|
9
|
+
'''
|
|
10
|
+
Extract metrics
|
|
11
|
+
'''
|
|
12
|
+
|
|
13
|
+
# Generic tool setup.
|
|
14
|
+
setup_tool(chip)
|
|
15
|
+
|
|
16
|
+
set_pnr_inputs(chip)
|
|
17
|
+
set_pnr_outputs(chip)
|
|
18
|
+
|
|
19
|
+
_set_reports(chip, [
|
|
20
|
+
'setup',
|
|
21
|
+
'hold',
|
|
22
|
+
'unconstrained',
|
|
23
|
+
'clock_skew',
|
|
24
|
+
'power',
|
|
25
|
+
'drv_violations',
|
|
26
|
+
'fmax',
|
|
27
|
+
|
|
28
|
+
# Images
|
|
29
|
+
'placement_density',
|
|
30
|
+
'routing_congestion',
|
|
31
|
+
'power_density',
|
|
32
|
+
'clock_placement',
|
|
33
|
+
'clock_trees',
|
|
34
|
+
'optimization_placement'
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def pre_process(chip):
|
|
39
|
+
or_pre_process(chip)
|
|
40
|
+
build_pex_corners(chip)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def post_process(chip):
|
|
44
|
+
or_post_process(chip)
|
|
@@ -326,6 +326,9 @@ def post_process(chip):
|
|
|
326
326
|
('vias', 'sc__step__route__vias', True, None),
|
|
327
327
|
('wirelength', 'sc__step__route__wirelength', True, 'distance'),
|
|
328
328
|
('cellarea', 'sc__metric__design__instance__area', True, 'area'),
|
|
329
|
+
('stdcellarea', 'sc__metric__design__instance__area__stdcell', True, 'area'),
|
|
330
|
+
('macroarea', 'sc__metric__design__instance__area__macros', True, 'area'),
|
|
331
|
+
('padcellarea', 'sc__metric__design__instance__area__padcells', True, 'area'),
|
|
329
332
|
('totalarea', 'sc__metric__design__core__area', True, 'area'),
|
|
330
333
|
('utilization', 'sc__metric__design__instance__utilization', True, 100.0),
|
|
331
334
|
('setuptns', 'sc__metric__timing__setup__tns', has_timing, 'time'),
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from siliconcompiler.tools._common import input_provides, get_tool_task
|
|
4
|
+
from siliconcompiler.tools._common.asic import set_tool_task_var
|
|
5
|
+
from siliconcompiler.tools.openroad.openroad import build_pex_corners
|
|
6
|
+
from siliconcompiler.tools.openroad.openroad import post_process as or_post_process
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def setup(chip):
|
|
10
|
+
'''
|
|
11
|
+
Perform floorplanning, pin placements, macro placements and power grid generation
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
# Generic tool setup.
|
|
15
|
+
# default tool settings, note, not additive!
|
|
16
|
+
|
|
17
|
+
tool = 'openroad'
|
|
18
|
+
script = 'sc_rdlroute.tcl'
|
|
19
|
+
refdir = os.path.join('tools', tool, 'scripts')
|
|
20
|
+
|
|
21
|
+
step = chip.get('arg', 'step')
|
|
22
|
+
index = chip.get('arg', 'index')
|
|
23
|
+
tool, task = get_tool_task(chip, step, index)
|
|
24
|
+
|
|
25
|
+
design = chip.top()
|
|
26
|
+
|
|
27
|
+
chip.set('tool', tool, 'exe', tool)
|
|
28
|
+
chip.set('tool', tool, 'vswitch', '-version')
|
|
29
|
+
chip.set('tool', tool, 'version', '>=v2.0-16839')
|
|
30
|
+
chip.set('tool', tool, 'format', 'tcl')
|
|
31
|
+
|
|
32
|
+
# exit automatically in batch mode and not breakpoint
|
|
33
|
+
option = ''
|
|
34
|
+
if exit and not chip.get('option', 'breakpoint', step=step, index=index):
|
|
35
|
+
option += " -exit"
|
|
36
|
+
|
|
37
|
+
option += " -metrics reports/metrics.json"
|
|
38
|
+
chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index)
|
|
39
|
+
|
|
40
|
+
# Input/Output requirements for default asicflow steps
|
|
41
|
+
|
|
42
|
+
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
43
|
+
step=step, index=index,
|
|
44
|
+
package='siliconcompiler')
|
|
45
|
+
chip.set('tool', tool, 'task', task, 'script', script,
|
|
46
|
+
step=step, index=index)
|
|
47
|
+
chip.set('tool', tool, 'task', task, 'threads', os.cpu_count(),
|
|
48
|
+
step=step, index=index, clobber=False)
|
|
49
|
+
|
|
50
|
+
if chip.get('option', 'nodisplay'):
|
|
51
|
+
# Tells QT to use the offscreen platform if nodisplay is used
|
|
52
|
+
chip.set('tool', tool, 'task', task, 'env', 'QT_QPA_PLATFORM', 'offscreen',
|
|
53
|
+
step=step, index=index)
|
|
54
|
+
|
|
55
|
+
# basic warning and error grep check on logfile
|
|
56
|
+
chip.set('tool', tool, 'task', task, 'regex', 'warnings', r'^\[WARNING|^Warning',
|
|
57
|
+
step=step, index=index, clobber=False)
|
|
58
|
+
chip.set('tool', tool, 'task', task, 'regex', 'errors', r'^\[ERROR',
|
|
59
|
+
step=step, index=index, clobber=False)
|
|
60
|
+
|
|
61
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
62
|
+
'option,var,openroad_libtype',
|
|
63
|
+
step=step, index=index)
|
|
64
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
65
|
+
','.join(['tool', tool, 'task', task, 'file', 'rdlroute']),
|
|
66
|
+
step=step, index=index)
|
|
67
|
+
chip.set('tool', tool, 'task', task, 'file', 'rdlroute',
|
|
68
|
+
'script to perform rdl route',
|
|
69
|
+
field='help')
|
|
70
|
+
|
|
71
|
+
set_tool_task_var(chip, param_key='fin_add_fill',
|
|
72
|
+
default_value='false',
|
|
73
|
+
schelp='true/false, when true enables adding fill, '
|
|
74
|
+
'if enabled by the PDK, to the design',
|
|
75
|
+
skip='lib')
|
|
76
|
+
|
|
77
|
+
if f'{design}.v' in input_provides(chip, step, index):
|
|
78
|
+
chip.add('tool', tool, 'task', task, 'input', design + '.v', step=step, index=index)
|
|
79
|
+
elif f'{design}.vg' in input_provides(chip, step, index):
|
|
80
|
+
chip.add('tool', tool, 'task', task, 'input', design + '.vg', step=step, index=index)
|
|
81
|
+
else:
|
|
82
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
83
|
+
','.join(['input', 'netlist', 'verilog']),
|
|
84
|
+
step=step, index=index)
|
|
85
|
+
|
|
86
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.sdc', step=step, index=index)
|
|
87
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.vg', step=step, index=index)
|
|
88
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.def', step=step, index=index)
|
|
89
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.odb', step=step, index=index)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def pre_process(chip):
|
|
93
|
+
build_pex_corners(chip)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def post_process(chip):
|
|
97
|
+
or_post_process(chip)
|
|
@@ -198,30 +198,28 @@ if { [file exists "inputs/$sc_design.odb"] } {
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
if {
|
|
201
|
+
if { [file exists "inputs/${sc_design}.def"] } {
|
|
202
|
+
# Read DEF
|
|
203
|
+
# get from previous step
|
|
204
|
+
puts "Reading DEF: inputs/${sc_design}.def"
|
|
205
|
+
read_def "inputs/${sc_design}.def"
|
|
206
|
+
} elseif { [sc_cfg_exists input layout def] } {
|
|
207
|
+
# Read DEF
|
|
208
|
+
set sc_def [lindex [sc_cfg_get input layout def] 0]
|
|
209
|
+
puts "Reading DEF: ${sc_def}"
|
|
210
|
+
read_def $sc_def
|
|
211
|
+
} elseif { [file exists "inputs/${sc_design}.vg"] } {
|
|
202
212
|
# Read Verilog
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
read_verilog "inputs/${sc_design}.vg"
|
|
206
|
-
} else {
|
|
207
|
-
foreach netlist [sc_cfg_get input netlist verilog] {
|
|
208
|
-
puts "Reading netlist verilog: ${netlist}"
|
|
209
|
-
read_verilog $netlist
|
|
210
|
-
}
|
|
211
|
-
}
|
|
213
|
+
puts "Reading netlist verilog: inputs/${sc_design}.vg"
|
|
214
|
+
read_verilog "inputs/${sc_design}.vg"
|
|
212
215
|
link_design $sc_design
|
|
213
216
|
} else {
|
|
214
|
-
# Read
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
read_def "inputs/${sc_design}.def"
|
|
219
|
-
} elseif { [sc_cfg_exists input layout def] } {
|
|
220
|
-
# Floorplan initialize handled separately in sc_floorplan.tcl
|
|
221
|
-
set sc_def [lindex [sc_cfg_get input layout def] 0]
|
|
222
|
-
puts "Reading DEF: ${sc_def}"
|
|
223
|
-
read_def $sc_def
|
|
217
|
+
# Read Verilog
|
|
218
|
+
foreach netlist [sc_cfg_get input netlist verilog] {
|
|
219
|
+
puts "Reading netlist verilog: ${netlist}"
|
|
220
|
+
read_verilog $netlist
|
|
224
221
|
}
|
|
222
|
+
link_design $sc_design
|
|
225
223
|
}
|
|
226
224
|
}
|
|
227
225
|
|
|
@@ -405,7 +403,7 @@ utl::info FLW 1 "Using $sc_rc_signal for signal parasitics estimation"
|
|
|
405
403
|
|
|
406
404
|
set_thread_count $sc_threads
|
|
407
405
|
|
|
408
|
-
if { $sc_task != "floorplan" } {
|
|
406
|
+
if { $sc_task != "floorplan" && $sc_task != "metrics" } {
|
|
409
407
|
## Setup global routing
|
|
410
408
|
|
|
411
409
|
# Adjust routing track density
|
|
@@ -504,7 +502,7 @@ if { $sc_task == "show" || $sc_task == "screenshot" } {
|
|
|
504
502
|
###############################
|
|
505
503
|
|
|
506
504
|
utl::push_metrics_stage "sc__metric__{}"
|
|
507
|
-
source "$sc_refdir/
|
|
505
|
+
source "$sc_refdir/sc_report.tcl"
|
|
508
506
|
utl::pop_metrics_stage
|
|
509
507
|
|
|
510
508
|
# Images
|