siliconcompiler 0.28.4__py3-none-any.whl → 0.28.5__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/core.py +3 -1
- 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/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 +45 -0
- siliconcompiler/tools/openroad/openroad.py +3 -0
- siliconcompiler/tools/openroad/rdlroute.py +97 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +1 -1
- 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.5.dist-info}/METADATA +4 -4
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.5.dist-info}/RECORD +41 -32
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.5.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.5.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.5.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.28.4.dist-info → siliconcompiler-0.28.5.dist-info}/top_level.txt +0 -0
|
@@ -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,45 @@
|
|
|
1
|
+
|
|
2
|
+
from siliconcompiler.tools.openroad.openroad import setup as setup_tool
|
|
3
|
+
from siliconcompiler.tools.openroad.openroad import build_pex_corners
|
|
4
|
+
from siliconcompiler.tools.openroad.openroad import post_process as or_post_process
|
|
5
|
+
from siliconcompiler.tools.openroad.openroad import pre_process as or_pre_process
|
|
6
|
+
from siliconcompiler.tools.openroad.openroad import _set_reports, set_pnr_inputs, set_pnr_outputs
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def setup(chip):
|
|
10
|
+
'''
|
|
11
|
+
Extract metrics
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
# Generic tool setup.
|
|
15
|
+
setup_tool(chip)
|
|
16
|
+
|
|
17
|
+
set_pnr_inputs(chip)
|
|
18
|
+
set_pnr_outputs(chip)
|
|
19
|
+
|
|
20
|
+
_set_reports(chip, [
|
|
21
|
+
'setup',
|
|
22
|
+
'hold',
|
|
23
|
+
'unconstrained',
|
|
24
|
+
'clock_skew',
|
|
25
|
+
'power',
|
|
26
|
+
'drv_violations',
|
|
27
|
+
'fmax',
|
|
28
|
+
|
|
29
|
+
# Images
|
|
30
|
+
'placement_density',
|
|
31
|
+
'routing_congestion',
|
|
32
|
+
'power_density',
|
|
33
|
+
'clock_placement',
|
|
34
|
+
'clock_trees',
|
|
35
|
+
'optimization_placement'
|
|
36
|
+
])
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def pre_process(chip):
|
|
40
|
+
or_pre_process(chip)
|
|
41
|
+
build_pex_corners(chip)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def post_process(chip):
|
|
45
|
+
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)
|
|
@@ -504,7 +504,7 @@ if { $sc_task == "show" || $sc_task == "screenshot" } {
|
|
|
504
504
|
###############################
|
|
505
505
|
|
|
506
506
|
utl::push_metrics_stage "sc__metric__{}"
|
|
507
|
-
source "$sc_refdir/
|
|
507
|
+
source "$sc_refdir/sc_report.tcl"
|
|
508
508
|
utl::pop_metrics_stage
|
|
509
509
|
|
|
510
510
|
# Images
|
|
@@ -1,170 +1 @@
|
|
|
1
|
-
###############################
|
|
2
|
-
# Report Metrics
|
|
3
|
-
###############################
|
|
4
1
|
|
|
5
|
-
proc sc_display_report { report } {
|
|
6
|
-
if { ![file exists $report] } {
|
|
7
|
-
return
|
|
8
|
-
}
|
|
9
|
-
set fid [open $report r]
|
|
10
|
-
set report_content [read $fid]
|
|
11
|
-
close $fid
|
|
12
|
-
puts $report_content
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
set fields "{capacitance slew input_pins nets fanout}"
|
|
16
|
-
set PREFIX "SC_METRIC:"
|
|
17
|
-
|
|
18
|
-
if { [sc_cfg_tool_task_check_in_list setup var reports] } {
|
|
19
|
-
puts "$PREFIX report_checks -path_delay max"
|
|
20
|
-
report_checks -fields $fields -path_delay max -format full_clock_expanded \
|
|
21
|
-
> reports/timing/setup.rpt
|
|
22
|
-
sc_display_report reports/timing/setup.rpt
|
|
23
|
-
report_checks -path_delay max -group_count $openroad_sta_top_n_paths \
|
|
24
|
-
> reports/timing/setup.topN.rpt
|
|
25
|
-
|
|
26
|
-
puts "$PREFIX setupslack"
|
|
27
|
-
report_worst_slack -max > reports/timing/worst_slack.setup.rpt
|
|
28
|
-
sc_display_report reports/timing/worst_slack.setup.rpt
|
|
29
|
-
report_worst_slack_metric -setup
|
|
30
|
-
|
|
31
|
-
puts "$PREFIX tns"
|
|
32
|
-
report_tns > reports/timing/total_negative_slack.rpt
|
|
33
|
-
sc_display_report reports/timing/total_negative_slack.rpt
|
|
34
|
-
report_tns_metric -setup
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if { [sc_cfg_tool_task_check_in_list hold var reports] } {
|
|
38
|
-
puts "$PREFIX report_checks -path_delay min"
|
|
39
|
-
report_checks -fields $fields -path_delay min -format full_clock_expanded \
|
|
40
|
-
> reports/timing/hold.rpt
|
|
41
|
-
sc_display_report reports/timing/hold.rpt
|
|
42
|
-
report_checks -path_delay min -group_count $openroad_sta_top_n_paths \
|
|
43
|
-
> reports/timing/hold.topN.rpt
|
|
44
|
-
|
|
45
|
-
puts "$PREFIX holdslack"
|
|
46
|
-
report_worst_slack -min > reports/timing/worst_slack.hold.rpt
|
|
47
|
-
sc_display_report reports/timing/worst_slack.hold.rpt
|
|
48
|
-
report_worst_slack_metric -hold
|
|
49
|
-
|
|
50
|
-
report_tns_metric -hold
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if { [sc_cfg_tool_task_check_in_list unconstrained var reports] } {
|
|
54
|
-
puts "$PREFIX unconstrained"
|
|
55
|
-
report_checks -fields $fields -unconstrained -format full_clock_expanded \
|
|
56
|
-
> reports/timing/unconstrained.rpt
|
|
57
|
-
sc_display_report reports/timing/unconstrained.rpt
|
|
58
|
-
report_checks -unconstrained -group_count $openroad_sta_top_n_paths \
|
|
59
|
-
> reports/timing/unconstrained.topN.rpt
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if {
|
|
63
|
-
[sc_cfg_tool_task_check_in_list clock_skew var reports] &&
|
|
64
|
-
[llength [all_clocks]] > 0
|
|
65
|
-
} {
|
|
66
|
-
puts "$PREFIX clock_skew"
|
|
67
|
-
report_clock_skew -setup -digits 4 > reports/timing/skew.setup.rpt
|
|
68
|
-
sc_display_report reports/timing/skew.setup.rpt
|
|
69
|
-
report_clock_skew_metric -setup
|
|
70
|
-
report_clock_skew -hold -digits 4 > reports/timing/skew.hold.rpt
|
|
71
|
-
sc_display_report reports/timing/skew.hold.rpt
|
|
72
|
-
report_clock_skew_metric -hold
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if { [sc_cfg_tool_task_check_in_list drv_violations var reports] } {
|
|
76
|
-
puts "$PREFIX DRV violators"
|
|
77
|
-
report_check_types -max_slew -max_capacitance -max_fanout -violators \
|
|
78
|
-
> reports/timing/drv_violators.rpt
|
|
79
|
-
sc_display_report reports/timing/drv_violators.rpt
|
|
80
|
-
report_erc_metrics
|
|
81
|
-
|
|
82
|
-
puts "$PREFIX floating nets"
|
|
83
|
-
report_floating_nets -verbose > reports/floating_nets.rpt
|
|
84
|
-
sc_display_report reports/floating_nets.rpt
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
utl::metric_int "timing__clocks" [llength [all_clocks]]
|
|
88
|
-
|
|
89
|
-
if { [sc_cfg_tool_task_check_in_list fmax var reports] } {
|
|
90
|
-
puts "$PREFIX fmax"
|
|
91
|
-
# Model on: https://github.com/The-OpenROAD-Project/OpenSTA/blob/f913c3ddbb3e7b4364ed4437c65ac78c4da9174b/tcl/Search.tcl#L1078
|
|
92
|
-
set fmax_metric 0
|
|
93
|
-
foreach clk [sta::sort_by_name [all_clocks]] {
|
|
94
|
-
set clk_name [get_name $clk]
|
|
95
|
-
set min_period [sta::find_clk_min_period $clk 1]
|
|
96
|
-
if { $min_period == 0.0 } {
|
|
97
|
-
continue
|
|
98
|
-
}
|
|
99
|
-
set fmax [expr { 1.0 / $min_period }]
|
|
100
|
-
utl::metric_float "timing__fmax__clock:${clk_name}" $fmax
|
|
101
|
-
puts "$clk_name fmax = [format %.2f [expr { $fmax / 1e6 }]] MHz"
|
|
102
|
-
set fmax_metric [expr { max($fmax_metric, $fmax) }]
|
|
103
|
-
}
|
|
104
|
-
if { $fmax_metric > 0 } {
|
|
105
|
-
utl::metric_float "timing__fmax" $fmax_metric
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
# get logic depth of design
|
|
110
|
-
utl::metric_int "design__logic__depth" [count_logic_depth]
|
|
111
|
-
|
|
112
|
-
if { [sc_cfg_tool_task_check_in_list power var reports] } {
|
|
113
|
-
puts "$PREFIX power"
|
|
114
|
-
foreach corner [sta::corners] {
|
|
115
|
-
set corner_name [$corner name]
|
|
116
|
-
puts "Power for corner: $corner_name"
|
|
117
|
-
report_power -corner $corner_name > reports/power/${corner_name}.rpt
|
|
118
|
-
sc_display_report reports/power/${corner_name}.rpt
|
|
119
|
-
}
|
|
120
|
-
report_power_metric -corner $sc_power_corner
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
puts "$PREFIX cellarea"
|
|
124
|
-
report_design_area
|
|
125
|
-
report_design_area_metrics
|
|
126
|
-
|
|
127
|
-
# get number of nets in design
|
|
128
|
-
utl::metric_int "design__nets" [llength [[ord::get_db_block] getNets]]
|
|
129
|
-
|
|
130
|
-
# get number of registers
|
|
131
|
-
utl::metric_int "design__registers" [llength [all_registers]]
|
|
132
|
-
|
|
133
|
-
# get number of buffers
|
|
134
|
-
set bufs 0
|
|
135
|
-
set invs 0
|
|
136
|
-
foreach inst [get_cells -hierarchical *] {
|
|
137
|
-
set cell [$inst cell]
|
|
138
|
-
if { $cell == "NULL" } {
|
|
139
|
-
continue
|
|
140
|
-
}
|
|
141
|
-
set liberty_cell [$cell liberty_cell]
|
|
142
|
-
if { $liberty_cell == "NULL" } {
|
|
143
|
-
continue
|
|
144
|
-
}
|
|
145
|
-
if { [$liberty_cell is_buffer] } {
|
|
146
|
-
incr bufs
|
|
147
|
-
} elseif { [$liberty_cell is_inverter] } {
|
|
148
|
-
incr invs
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
utl::metric_int "design__buffers" $bufs
|
|
152
|
-
utl::metric_int "design__inverters" $invs
|
|
153
|
-
|
|
154
|
-
# get number of unconstrained endpoints
|
|
155
|
-
with_output_to_variable endpoints {check_setup -unconstrained_endpoints}
|
|
156
|
-
set unconstrained_endpoints [regexp -all -inline {[0-9]+} $endpoints]
|
|
157
|
-
if { $unconstrained_endpoints == "" } {
|
|
158
|
-
set unconstrained_endpoints 0
|
|
159
|
-
}
|
|
160
|
-
utl::metric_int "timing__unconstrained" $unconstrained_endpoints
|
|
161
|
-
|
|
162
|
-
# Write markers
|
|
163
|
-
foreach markerdb [[ord::get_db_block] getMarkerCategories] {
|
|
164
|
-
if { [$markerdb getMarkerCount] == 0 } {
|
|
165
|
-
continue
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
$markerdb writeTR "reports/markers/${sc_design}.[$markerdb getName].rpt"
|
|
169
|
-
$markerdb writeJSON "reports/markers/${sc_design}.[$markerdb getName].json"
|
|
170
|
-
}
|