siliconcompiler 0.28.9__py3-none-any.whl → 0.29.0__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/sc_remote.py +15 -14
- siliconcompiler/apps/sc_show.py +5 -5
- siliconcompiler/apps/utils/replay.py +136 -0
- siliconcompiler/core.py +14 -12
- siliconcompiler/flows/_common.py +11 -13
- siliconcompiler/flows/asicflow.py +83 -42
- siliconcompiler/remote/__init__.py +11 -0
- siliconcompiler/remote/client.py +753 -815
- siliconcompiler/report/report.py +2 -0
- siliconcompiler/report/summary_table.py +1 -1
- siliconcompiler/scheduler/__init__.py +51 -9
- siliconcompiler/schema/schema_cfg.py +15 -3
- siliconcompiler/schema/schema_obj.py +16 -0
- siliconcompiler/sphinx_ext/dynamicgen.py +4 -3
- siliconcompiler/targets/gf180_demo.py +3 -3
- siliconcompiler/templates/replay/requirements.txt +6 -0
- siliconcompiler/templates/replay/run.py.j2 +22 -0
- siliconcompiler/templates/replay/setup.sh +17 -0
- siliconcompiler/tools/_common/__init__.py +15 -1
- siliconcompiler/tools/_common/asic.py +10 -3
- siliconcompiler/tools/builtin/concatenate.py +1 -1
- siliconcompiler/tools/openroad/__init__.py +103 -0
- siliconcompiler/tools/openroad/{openroad.py → _apr.py} +413 -422
- siliconcompiler/tools/openroad/antenna_repair.py +78 -0
- siliconcompiler/tools/openroad/clock_tree_synthesis.py +64 -0
- siliconcompiler/tools/openroad/detailed_placement.py +59 -0
- siliconcompiler/tools/openroad/detailed_route.py +62 -0
- siliconcompiler/tools/openroad/endcap_tapcell_insertion.py +52 -0
- siliconcompiler/tools/openroad/fillercell_insertion.py +58 -0
- siliconcompiler/tools/openroad/{dfm.py → fillmetal_insertion.py} +35 -19
- siliconcompiler/tools/openroad/global_placement.py +58 -0
- siliconcompiler/tools/openroad/global_route.py +63 -0
- siliconcompiler/tools/openroad/init_floorplan.py +103 -0
- siliconcompiler/tools/openroad/macro_placement.py +65 -0
- siliconcompiler/tools/openroad/metrics.py +23 -8
- siliconcompiler/tools/openroad/pin_placement.py +56 -0
- siliconcompiler/tools/openroad/power_grid.py +65 -0
- siliconcompiler/tools/openroad/rcx_bench.py +7 -4
- siliconcompiler/tools/openroad/rcx_extract.py +2 -1
- siliconcompiler/tools/openroad/rdlroute.py +4 -4
- siliconcompiler/tools/openroad/repair_design.py +59 -0
- siliconcompiler/tools/openroad/repair_timing.py +63 -0
- siliconcompiler/tools/openroad/screenshot.py +9 -20
- siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +44 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +95 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +51 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +62 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +41 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +71 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +55 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +27 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +36 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +26 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +61 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +333 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +123 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +22 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +41 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +60 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +68 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +83 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +125 -0
- siliconcompiler/tools/openroad/scripts/common/debugging.tcl +28 -0
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +675 -0
- siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +59 -0
- siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/common/read_timing_constraints.tcl +16 -0
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +180 -0
- siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +18 -0
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +395 -0
- siliconcompiler/tools/openroad/scripts/{sc_rcx_bench.tcl → rcx/sc_rcx_bench.tcl} +5 -5
- siliconcompiler/tools/openroad/scripts/{sc_rcx_extract.tcl → rcx/sc_rcx_extract.tcl} +0 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +5 -16
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +51 -51
- siliconcompiler/tools/openroad/scripts/sc_show.tcl +105 -0
- siliconcompiler/tools/openroad/show.py +28 -23
- siliconcompiler/tools/openroad/{export.py → write_data.py} +31 -26
- siliconcompiler/tools/opensta/__init__.py +1 -1
- siliconcompiler/tools/yosys/syn_asic.py +7 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +27 -6
- siliconcompiler/tools/yosys/syn_fpga.tcl +26 -18
- siliconcompiler/toolscripts/_tools.json +4 -4
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/METADATA +14 -12
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/RECORD +90 -63
- siliconcompiler/tools/openroad/cts.py +0 -45
- siliconcompiler/tools/openroad/floorplan.py +0 -75
- siliconcompiler/tools/openroad/physyn.py +0 -27
- siliconcompiler/tools/openroad/place.py +0 -41
- siliconcompiler/tools/openroad/route.py +0 -45
- siliconcompiler/tools/openroad/scripts/__init__.py +0 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +0 -514
- siliconcompiler/tools/openroad/scripts/sc_cts.tcl +0 -68
- siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +0 -22
- siliconcompiler/tools/openroad/scripts/sc_export.tcl +0 -100
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +0 -456
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +0 -1
- siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +0 -6
- siliconcompiler/tools/openroad/scripts/sc_place.tcl +0 -84
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +0 -494
- siliconcompiler/tools/openroad/scripts/sc_report.tcl +0 -189
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +0 -143
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +0 -18
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +0 -393
- /siliconcompiler/tools/openroad/scripts/{sc_write.tcl → common/write_data.tcl} +0 -0
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/top_level.txt +0 -0
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
'''
|
|
2
|
-
OpenROAD is an automated physical design platform for
|
|
3
|
-
integrated circuit design with a complete set of features
|
|
4
|
-
needed to translate a synthesized netlist to a tapeout ready
|
|
5
|
-
GDSII.
|
|
6
|
-
|
|
7
|
-
Documentation: https://openroad.readthedocs.io/
|
|
8
|
-
|
|
9
|
-
Sources: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
10
|
-
|
|
11
|
-
Installation: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
12
|
-
'''
|
|
13
|
-
|
|
14
1
|
import os
|
|
15
2
|
import json
|
|
16
3
|
from siliconcompiler import sc_open
|
|
@@ -19,49 +6,19 @@ from siliconcompiler.tools._common import input_provides, add_common_file, \
|
|
|
19
6
|
get_tool_task, record_metric
|
|
20
7
|
from siliconcompiler.tools._common.asic import get_mainlib, set_tool_task_var, get_libraries, \
|
|
21
8
|
CellArea
|
|
22
|
-
from siliconcompiler.
|
|
9
|
+
from siliconcompiler.tools.openroad import setup as tool_setup
|
|
23
10
|
|
|
24
11
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
####################################################################
|
|
28
|
-
def make_docs(chip):
|
|
29
|
-
chip.use(asap7_demo)
|
|
12
|
+
def setup(chip, exit=True):
|
|
13
|
+
tool_setup(chip, exit=exit)
|
|
30
14
|
|
|
31
|
-
|
|
32
|
-
################################
|
|
33
|
-
# Setup Tool (pre executable)
|
|
34
|
-
################################
|
|
35
|
-
def setup_tool(chip, exit=True, clobber=True):
|
|
36
15
|
step = chip.get('arg', 'step')
|
|
37
16
|
index = chip.get('arg', 'index')
|
|
38
17
|
tool, task = get_tool_task(chip, step, index)
|
|
39
18
|
|
|
40
|
-
chip.set('tool', tool, '
|
|
41
|
-
|
|
42
|
-
chip.set('tool', tool, 'version', '>=v2.0-16580', clobber=clobber)
|
|
43
|
-
chip.set('tool', tool, 'format', 'tcl', clobber=clobber)
|
|
44
|
-
|
|
45
|
-
# exit automatically in batch mode and not breakpoint
|
|
46
|
-
option = ''
|
|
47
|
-
if exit and not chip.get('option', 'breakpoint', step=step, index=index):
|
|
48
|
-
option += " -exit"
|
|
49
|
-
|
|
50
|
-
option += " -metrics reports/metrics.json"
|
|
51
|
-
chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index, clobber=clobber)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def setup(chip):
|
|
55
|
-
|
|
56
|
-
# default tool settings, note, not additive!
|
|
57
|
-
|
|
58
|
-
tool = 'openroad'
|
|
59
|
-
script = 'sc_apr.tcl'
|
|
60
|
-
refdir = os.path.join('tools', tool, 'scripts')
|
|
19
|
+
chip.set('tool', tool, 'task', task, 'threads', os.cpu_count(),
|
|
20
|
+
step=step, index=index)
|
|
61
21
|
|
|
62
|
-
step = chip.get('arg', 'step')
|
|
63
|
-
index = chip.get('arg', 'index')
|
|
64
|
-
_, task = get_tool_task(chip, step, index)
|
|
65
22
|
pdkname = chip.get('option', 'pdk')
|
|
66
23
|
targetlibs = get_libraries(chip, 'logic')
|
|
67
24
|
mainlib = get_mainlib(chip)
|
|
@@ -70,221 +27,122 @@ def setup(chip):
|
|
|
70
27
|
delaymodel = chip.get('asic', 'delaymodel', step=step, index=index)
|
|
71
28
|
libtype = chip.get('library', mainlib, 'asic', 'libarch', step=step, index=index)
|
|
72
29
|
|
|
73
|
-
is_screenshot = task == 'screenshot'
|
|
74
|
-
is_show_screenshot = task == 'show' or is_screenshot
|
|
75
|
-
|
|
76
|
-
if is_show_screenshot:
|
|
77
|
-
clobber = True
|
|
78
|
-
else:
|
|
79
|
-
clobber = False
|
|
80
|
-
|
|
81
|
-
# Fixed for tool
|
|
82
|
-
setup_tool(chip, exit=task != 'show', clobber=clobber)
|
|
83
|
-
|
|
84
|
-
# Input/Output requirements for default asicflow steps
|
|
85
|
-
|
|
86
|
-
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
87
|
-
step=step, index=index,
|
|
88
|
-
package='siliconcompiler', clobber=clobber)
|
|
89
|
-
chip.set('tool', tool, 'task', task, 'script', script,
|
|
90
|
-
step=step, index=index, clobber=clobber)
|
|
91
|
-
chip.set('tool', tool, 'task', task, 'threads', os.cpu_count(),
|
|
92
|
-
step=step, index=index, clobber=clobber)
|
|
93
|
-
|
|
94
|
-
if chip.get('option', 'nodisplay'):
|
|
95
|
-
# Tells QT to use the offscreen platform if nodisplay is used
|
|
96
|
-
chip.set('tool', tool, 'task', task, 'env', 'QT_QPA_PLATFORM', 'offscreen',
|
|
97
|
-
step=step, index=index)
|
|
98
|
-
|
|
99
30
|
if delaymodel != 'nldm':
|
|
100
|
-
chip.
|
|
31
|
+
chip.error(f'{delaymodel} delay model is not supported by {tool}, only nldm')
|
|
101
32
|
|
|
102
|
-
if stackup
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
33
|
+
if not stackup or not targetlibs:
|
|
34
|
+
chip.error('Stackup and logiclib parameters required for OpenROAD.')
|
|
35
|
+
|
|
36
|
+
# Setup general required
|
|
37
|
+
chip.add('tool', tool, 'task', task, 'require', 'asic,logiclib',
|
|
38
|
+
step=step, index=index)
|
|
39
|
+
if chip.get('asic', 'macrolib', step=step, index=index):
|
|
40
|
+
chip.add('tool', tool, 'task', task, 'require', 'asic,macrolib',
|
|
109
41
|
step=step, index=index)
|
|
110
|
-
|
|
111
|
-
|
|
42
|
+
if chip.get('option', 'library', step=step, index=index):
|
|
43
|
+
chip.add('tool', tool, 'task', task, 'require', 'option,library',
|
|
112
44
|
step=step, index=index)
|
|
45
|
+
chip.add('tool', tool, 'task', task, 'require', 'asic,delaymodel',
|
|
46
|
+
step=step, index=index)
|
|
47
|
+
chip.add('tool', tool, 'task', task, 'require', 'option,stackup',
|
|
48
|
+
step=step, index=index)
|
|
49
|
+
chip.add('tool', tool, 'task', task, 'require', f'library,{mainlib},asic,libarch',
|
|
50
|
+
step=step, index=index)
|
|
51
|
+
chip.add('tool', tool, 'task', task, 'require', f'library,{mainlib},asic,site,{libtype}',
|
|
52
|
+
step=step, index=index)
|
|
53
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
54
|
+
f'pdk,{pdkname},aprtech,openroad,{stackup},{libtype},lef',
|
|
55
|
+
step=step, index=index)
|
|
56
|
+
|
|
57
|
+
# Add library requirements
|
|
58
|
+
for lib in targetlibs:
|
|
59
|
+
for timing_key in get_library_timing_keypaths(chip, lib).values():
|
|
60
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(timing_key),
|
|
61
|
+
step=step, index=index)
|
|
113
62
|
chip.add('tool', tool, 'task', task, 'require',
|
|
114
|
-
",".join(['
|
|
63
|
+
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
115
64
|
step=step, index=index)
|
|
116
|
-
|
|
117
|
-
for
|
|
118
|
-
|
|
65
|
+
for lib in macrolibs:
|
|
66
|
+
for timing_key in get_library_timing_keypaths(chip, lib).values():
|
|
67
|
+
if chip.valid(*timing_key):
|
|
119
68
|
chip.add('tool', tool, 'task', task, 'require', ",".join(timing_key),
|
|
120
69
|
step=step, index=index)
|
|
121
|
-
chip.add('tool', tool, 'task', task, 'require',
|
|
122
|
-
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
123
|
-
step=step, index=index)
|
|
124
|
-
for lib in macrolibs:
|
|
125
|
-
for timing_key in get_library_timing_keypaths(chip, lib).values():
|
|
126
|
-
if chip.valid(*timing_key):
|
|
127
|
-
chip.add('tool', tool, 'task', task, 'require', ",".join(timing_key),
|
|
128
|
-
step=step, index=index)
|
|
129
|
-
chip.add('tool', tool, 'task', task, 'require',
|
|
130
|
-
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
131
|
-
step=step, index=index)
|
|
132
|
-
else:
|
|
133
|
-
chip.error('Stackup and logiclib parameters required for OpenROAD.')
|
|
134
|
-
|
|
135
|
-
# Set required keys
|
|
136
|
-
for var0, var1 in [('openroad_tielow_cell', 'openroad_tielow_port'),
|
|
137
|
-
('openroad_tiehigh_cell', 'openroad_tiehigh_port')]:
|
|
138
|
-
key0 = ['library', mainlib, 'option', 'var', tool, var0]
|
|
139
|
-
key1 = ['library', mainlib, 'option', 'var', tool, var1]
|
|
140
|
-
if chip.valid(*key0):
|
|
141
|
-
chip.add('tool', tool, 'task', task, 'require', ",".join(key1), step=step, index=index)
|
|
142
|
-
if chip.valid(*key1):
|
|
143
|
-
chip.add('tool', tool, 'task', task, 'require', ",".join(key0), step=step, index=index)
|
|
144
|
-
|
|
145
|
-
for key in (['pdk', pdkname, 'var', 'openroad', 'rclayer_signal', stackup],
|
|
146
|
-
['pdk', pdkname, 'var', 'openroad', 'rclayer_clock', stackup],
|
|
147
|
-
['pdk', pdkname, 'var', 'openroad', 'pin_layer_horizontal', stackup],
|
|
148
|
-
['pdk', pdkname, 'var', 'openroad', 'pin_layer_vertical', stackup]):
|
|
149
70
|
chip.add('tool', tool, 'task', task, 'require',
|
|
150
|
-
",".join(
|
|
71
|
+
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
151
72
|
step=step, index=index)
|
|
152
73
|
|
|
153
|
-
# set default values for openroad
|
|
154
|
-
_define_ord_params(chip)
|
|
155
|
-
_define_sta_params(chip)
|
|
156
|
-
_define_sdc_params(chip)
|
|
157
|
-
_define_ifp_params(chip)
|
|
158
|
-
_define_pad_params(chip)
|
|
159
|
-
_define_ppl_params(chip)
|
|
160
|
-
_define_mpl_params(chip)
|
|
161
|
-
_define_pdn_params(chip)
|
|
162
|
-
_define_psm_params(chip)
|
|
163
|
-
_define_gpl_params(chip)
|
|
164
|
-
_define_dpl_params(chip)
|
|
165
|
-
_define_dpo_params(chip)
|
|
166
|
-
_define_cts_params(chip)
|
|
167
|
-
_define_rsz_params(chip)
|
|
168
|
-
_define_grt_params(chip)
|
|
169
|
-
_define_ant_params(chip)
|
|
170
|
-
_define_drt_params(chip)
|
|
171
|
-
_define_fin_params(chip)
|
|
172
|
-
_define_pex_params(chip)
|
|
173
74
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
chip.set('tool', tool, 'task', task, 'regex', 'warnings', r'^\[WARNING|^Warning',
|
|
178
|
-
step=step, index=index, clobber=False)
|
|
179
|
-
chip.set('tool', tool, 'task', task, 'regex', 'errors', r'^\[ERROR',
|
|
180
|
-
step=step, index=index, clobber=False)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
################################
|
|
184
|
-
# Version Check
|
|
185
|
-
################################
|
|
186
|
-
def parse_version(stdout):
|
|
187
|
-
# stdout will be in one of the following forms:
|
|
188
|
-
# - 1 08de3b46c71e329a10aa4e753dcfeba2ddf54ddd
|
|
189
|
-
# - 1 v2.0-880-gd1c7001ad
|
|
190
|
-
# - v2.0-1862-g0d785bd84
|
|
191
|
-
|
|
192
|
-
# strip off the "1" prefix if it's there
|
|
193
|
-
version = stdout.split()[-1]
|
|
194
|
-
|
|
195
|
-
pieces = version.split('-')
|
|
196
|
-
if len(pieces) > 1:
|
|
197
|
-
# strip off the hash in the new version style
|
|
198
|
-
return '-'.join(pieces[:-1])
|
|
199
|
-
else:
|
|
200
|
-
return pieces[0]
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def normalize_version(version):
|
|
204
|
-
if '.' in version:
|
|
205
|
-
return version.lstrip('v')
|
|
206
|
-
else:
|
|
207
|
-
return '0'
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
def pre_process(chip):
|
|
211
|
-
step = chip.get('arg', 'step')
|
|
212
|
-
index = chip.get('arg', 'index')
|
|
213
|
-
tool, task = get_tool_task(chip, step, index)
|
|
214
|
-
pdkname = chip.get('option', 'pdk')
|
|
215
|
-
targetlibs = get_libraries(chip, 'logic')
|
|
216
|
-
macrolibs = get_libraries(chip, 'macro')
|
|
217
|
-
mainlib = get_mainlib(chip)
|
|
218
|
-
stackup = chip.get('option', 'stackup')
|
|
219
|
-
libtype = chip.get('library', mainlib, 'asic', 'libarch', step=step, index=index)
|
|
220
|
-
|
|
221
|
-
# set tapcell file
|
|
222
|
-
tapfile = None
|
|
223
|
-
if chip.valid('library', mainlib, 'option', 'file', 'openroad_tapcells'):
|
|
224
|
-
tapfile = chip.find_files('library', mainlib, 'option', 'file', 'openroad_tapcells')
|
|
225
|
-
elif chip.valid('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells'):
|
|
226
|
-
tapfile = chip.find_files('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells')
|
|
227
|
-
if tapfile:
|
|
228
|
-
chip.set('tool', tool, 'task', task, 'file', 'ifp_tapcell', tapfile,
|
|
229
|
-
step=step, index=index, clobber=False)
|
|
230
|
-
|
|
231
|
-
for libvar, openroadvar in [('openroad_pdngen', 'pdn_config'),
|
|
232
|
-
('openroad_global_connect', 'global_connect')]:
|
|
233
|
-
if chip.valid('tool', tool, 'task', task, 'file', openroadvar) and \
|
|
234
|
-
chip.get('tool', tool, 'task', task, 'file', openroadvar, step=step, index=index):
|
|
235
|
-
# value already set
|
|
236
|
-
continue
|
|
237
|
-
|
|
238
|
-
# copy from libs
|
|
239
|
-
for lib in targetlibs + macrolibs:
|
|
240
|
-
if chip.valid('library', lib, 'option', 'file', libvar):
|
|
241
|
-
for vfile in chip.find_files('library', lib, 'option', 'file', libvar):
|
|
242
|
-
chip.add('tool', tool, 'task', task, 'file', openroadvar, vfile,
|
|
243
|
-
step=step, index=index)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
################################
|
|
247
|
-
# Post_process (post executable)
|
|
248
|
-
################################
|
|
249
|
-
def post_process(chip):
|
|
250
|
-
''' Tool specific function to run after step execution
|
|
75
|
+
def extract_metrics(chip):
|
|
76
|
+
'''
|
|
77
|
+
Extract metrics
|
|
251
78
|
'''
|
|
252
79
|
|
|
253
80
|
# Check log file for errors and statistics
|
|
254
81
|
step = chip.get('arg', 'step')
|
|
255
82
|
index = chip.get('arg', 'index')
|
|
256
|
-
tool, task = get_tool_task(chip, step, index)
|
|
257
83
|
|
|
258
84
|
metric_reports = {
|
|
259
|
-
"setuptns": [
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
85
|
+
"setuptns": [
|
|
86
|
+
"timing/total_negative_slack.rpt",
|
|
87
|
+
"timing/setup.rpt"
|
|
88
|
+
],
|
|
89
|
+
"setupslack": [
|
|
90
|
+
"timing/worst_slack.setup.rpt",
|
|
91
|
+
"timing/setup.rpt",
|
|
92
|
+
"timing/setup.topN.rpt"
|
|
93
|
+
],
|
|
94
|
+
"setupskew": [
|
|
95
|
+
"timing/skew.setup.rpt",
|
|
96
|
+
"timing/worst_slack.setup.rpt",
|
|
97
|
+
"timing/setup.rpt",
|
|
98
|
+
"timing/setup.topN.rpt"
|
|
99
|
+
],
|
|
100
|
+
"setuppaths": [
|
|
101
|
+
"timing/setup.rpt",
|
|
102
|
+
"timing/setup.topN.rpt"
|
|
103
|
+
],
|
|
104
|
+
"holdslack": [
|
|
105
|
+
"timing/worst_slack.hold.rpt",
|
|
106
|
+
"timing/hold.rpt",
|
|
107
|
+
"timing/hold.topN.rpt"
|
|
108
|
+
],
|
|
109
|
+
"holdskew": [
|
|
110
|
+
"timing/skew.hold.rpt",
|
|
111
|
+
"timing/worst_slack.hold.rpt",
|
|
112
|
+
"timing/hold.rpt",
|
|
113
|
+
"timing/hold.topN.rpt"
|
|
114
|
+
],
|
|
115
|
+
"holdpaths": [
|
|
116
|
+
"timing/hold.rpt",
|
|
117
|
+
"timing/hold.topN.rpt"
|
|
118
|
+
],
|
|
119
|
+
"unconstrained": [
|
|
120
|
+
"timing/unconstrained.rpt",
|
|
121
|
+
"timing/unconstrained.topN.rpt"
|
|
122
|
+
],
|
|
273
123
|
"peakpower": [
|
|
274
124
|
*[f"power/{corner}.rpt" for corner in chip.getkeys('constraint', 'timing')],
|
|
275
125
|
*[f"images/heatmap/power_density/{corner}.png"
|
|
276
126
|
for corner in chip.getkeys('constraint', 'timing')]
|
|
277
127
|
],
|
|
278
|
-
"drvs": [
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
128
|
+
"drvs": [
|
|
129
|
+
"timing/drv_violators.rpt",
|
|
130
|
+
"floating_nets.rpt",
|
|
131
|
+
f"{chip.design}_antenna.rpt",
|
|
132
|
+
f"{chip.design}_antenna_post_repair.rpt"
|
|
133
|
+
],
|
|
134
|
+
"drcs": [
|
|
135
|
+
f"{chip.design}_drc.rpt",
|
|
136
|
+
f"markers/{chip.design}.drc.rpt",
|
|
137
|
+
f"markers/{chip.design}.drc.json",
|
|
138
|
+
f"images/markers/{chip.design}.DRC.png"
|
|
139
|
+
],
|
|
140
|
+
"utilization": [
|
|
141
|
+
"images/heatmap/placement_density.png"
|
|
142
|
+
],
|
|
143
|
+
"wirelength": [
|
|
144
|
+
f"images/{chip.design}.routing.png"
|
|
145
|
+
]
|
|
288
146
|
}
|
|
289
147
|
metric_reports["leakagepower"] = metric_reports["peakpower"]
|
|
290
148
|
|
|
@@ -310,13 +168,14 @@ def post_process(chip):
|
|
|
310
168
|
_generate_cell_area_report(chip.top(), metrics)
|
|
311
169
|
|
|
312
170
|
or_units = {}
|
|
313
|
-
for unit, or_unit in [
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
171
|
+
for unit, or_unit in [
|
|
172
|
+
('time', 'run__flow__platform__time_units'),
|
|
173
|
+
('capacitance', 'run__flow__platform__capacitance_units'),
|
|
174
|
+
('resistance', 'run__flow__platform__resistance_units'),
|
|
175
|
+
('volt', 'run__flow__platform__voltage_units'),
|
|
176
|
+
('amp', 'run__flow__platform__current_units'),
|
|
177
|
+
('power', 'run__flow__platform__power_units'),
|
|
178
|
+
('distance', 'run__flow__platform__distance_units')]:
|
|
320
179
|
if or_unit in metrics:
|
|
321
180
|
# Remove first digit
|
|
322
181
|
metric_unit = metrics[or_unit][1:]
|
|
@@ -414,11 +273,12 @@ def post_process(chip):
|
|
|
414
273
|
source_unit=wns_units)
|
|
415
274
|
|
|
416
275
|
drvs = None
|
|
417
|
-
for metric in [
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
276
|
+
for metric in [
|
|
277
|
+
'sc__metric__timing__drv__max_slew',
|
|
278
|
+
'sc__metric__timing__drv__max_cap',
|
|
279
|
+
'sc__metric__timing__drv__max_fanout',
|
|
280
|
+
'sc__metric__antenna__violating__nets',
|
|
281
|
+
'sc__metric__antenna__violating__pins']:
|
|
422
282
|
if metric in metrics:
|
|
423
283
|
if drvs is None:
|
|
424
284
|
drvs = int(metrics[metric])
|
|
@@ -541,171 +401,138 @@ def _generate_cell_area_report(design, ord_metrics):
|
|
|
541
401
|
cellarea_report.writeReport("reports/hierarchical_cell_area.json")
|
|
542
402
|
|
|
543
403
|
|
|
544
|
-
|
|
545
|
-
def get_library_timing_keypaths(chip, lib):
|
|
404
|
+
def define_tapcell_params(chip):
|
|
546
405
|
step = chip.get('arg', 'step')
|
|
547
406
|
index = chip.get('arg', 'index')
|
|
407
|
+
tool, task = get_tool_task(chip, step, index)
|
|
548
408
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
for corner in corners:
|
|
554
|
-
if chip.valid('library', lib, 'output', corner, delaymodel):
|
|
555
|
-
keypaths[constraint] = ('library', lib, 'output', corner, delaymodel)
|
|
556
|
-
|
|
557
|
-
if constraint not in keypaths:
|
|
558
|
-
keypaths[constraint] = ('library', lib, 'output', corners[0], delaymodel)
|
|
559
|
-
return keypaths
|
|
560
|
-
|
|
409
|
+
# Files
|
|
410
|
+
chip.set('tool', tool, 'task', task, 'file', 'ifp_tapcell',
|
|
411
|
+
'tap cell insertion script',
|
|
412
|
+
field='help')
|
|
561
413
|
|
|
562
|
-
def get_pex_corners(chip):
|
|
563
414
|
|
|
415
|
+
def define_tapcell_files(chip):
|
|
564
416
|
step = chip.get('arg', 'step')
|
|
565
417
|
index = chip.get('arg', 'index')
|
|
418
|
+
tool, task = get_tool_task(chip, step, index)
|
|
566
419
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
corners.add(pexcorner)
|
|
420
|
+
pdkname = chip.get('option', 'pdk')
|
|
421
|
+
mainlib = get_mainlib(chip)
|
|
422
|
+
stackup = chip.get('option', 'stackup')
|
|
423
|
+
libtype = chip.get('library', mainlib, 'asic', 'libarch',
|
|
424
|
+
step=step, index=index)
|
|
573
425
|
|
|
574
|
-
|
|
426
|
+
# set tapcell file
|
|
427
|
+
tapfile = None
|
|
428
|
+
if chip.valid('library', mainlib, 'option', 'file', 'openroad_tapcells'):
|
|
429
|
+
tapfile = chip.find_files('library', mainlib, 'option', 'file', 'openroad_tapcells')
|
|
430
|
+
elif chip.valid('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells'):
|
|
431
|
+
tapfile = chip.find_files('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells')
|
|
432
|
+
if tapfile:
|
|
433
|
+
chip.set('tool', tool, 'task', task, 'file', 'ifp_tapcell', tapfile,
|
|
434
|
+
step=step, index=index, clobber=False)
|
|
575
435
|
|
|
576
436
|
|
|
577
|
-
def
|
|
437
|
+
def define_tiecell_params(chip):
|
|
438
|
+
set_tool_task_var(chip, param_key='ifp_tie_separation',
|
|
439
|
+
default_value='0',
|
|
440
|
+
schelp='maximum distance between tie high/low cells in microns')
|
|
441
|
+
|
|
578
442
|
step = chip.get('arg', 'step')
|
|
579
443
|
index = chip.get('arg', 'index')
|
|
444
|
+
tool, task = get_tool_task(chip, step, index)
|
|
580
445
|
|
|
581
|
-
|
|
582
|
-
if check in chip.get('constraint', 'timing', constraint, 'check',
|
|
583
|
-
step=step, index=index):
|
|
584
|
-
return constraint
|
|
585
|
-
|
|
586
|
-
# if not specified, just pick the first constraint available
|
|
587
|
-
return chip.getkeys('constraint', 'timing')[0]
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
def get_power_corner(chip):
|
|
591
|
-
return get_constraint_by_check(chip, "power")
|
|
446
|
+
mainlib = get_mainlib(chip)
|
|
592
447
|
|
|
448
|
+
# Set required keys
|
|
449
|
+
for var0, var1 in [('openroad_tielow_cell', 'openroad_tielow_port'),
|
|
450
|
+
('openroad_tiehigh_cell', 'openroad_tiehigh_port')]:
|
|
451
|
+
key0 = ['library', mainlib, 'option', 'var', tool, var0]
|
|
452
|
+
key1 = ['library', mainlib, 'option', 'var', tool, var1]
|
|
453
|
+
if chip.valid(*key0):
|
|
454
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key1),
|
|
455
|
+
step=step, index=index)
|
|
456
|
+
if chip.valid(*key1):
|
|
457
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key0),
|
|
458
|
+
step=step, index=index)
|
|
593
459
|
|
|
594
|
-
def get_setup_corner(chip):
|
|
595
|
-
return get_constraint_by_check(chip, "setup")
|
|
596
460
|
|
|
461
|
+
def define_ppl_params(chip):
|
|
462
|
+
set_tool_task_var(chip, param_key='ppl_arguments',
|
|
463
|
+
default_value=[],
|
|
464
|
+
schelp='additional arguments to pass along to the pin placer.')
|
|
597
465
|
|
|
598
|
-
def build_pex_corners(chip):
|
|
599
466
|
step = chip.get('arg', 'step')
|
|
600
467
|
index = chip.get('arg', 'index')
|
|
601
468
|
tool, task = get_tool_task(chip, step, index)
|
|
602
469
|
|
|
470
|
+
chip.set('tool', tool, 'task', task, 'file', 'ppl_constraints',
|
|
471
|
+
'pin placement constraints script',
|
|
472
|
+
field='help')
|
|
473
|
+
|
|
603
474
|
pdkname = chip.get('option', 'pdk')
|
|
604
475
|
stackup = chip.get('option', 'stackup')
|
|
605
476
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
if not pexcorner:
|
|
612
|
-
continue
|
|
613
|
-
corners[constraint] = pexcorner
|
|
614
|
-
|
|
615
|
-
default_corner = get_setup_corner(chip)
|
|
616
|
-
if default_corner in corners:
|
|
617
|
-
corners[None] = corners[default_corner]
|
|
618
|
-
|
|
619
|
-
chip.set('tool', tool, 'task', task, 'file', 'parasitics',
|
|
620
|
-
os.path.join(chip.getworkdir(step=step, index=index), 'inputs', 'sc_parasitics.tcl'),
|
|
621
|
-
step=step, index=index, clobber=True)
|
|
622
|
-
|
|
623
|
-
with open(chip.get('tool', tool, 'task', task, 'file', 'parasitics',
|
|
624
|
-
step=step, index=index)[0], 'w') as f:
|
|
625
|
-
for constraint, pexcorner in corners.items():
|
|
626
|
-
if chip.valid('pdk', pdkname, 'pexmodel', tool, stackup, pexcorner):
|
|
627
|
-
pex_source_file = chip.find_files('pdk', pdkname,
|
|
628
|
-
'pexmodel',
|
|
629
|
-
tool,
|
|
630
|
-
stackup,
|
|
631
|
-
pexcorner)[0]
|
|
632
|
-
if not pex_source_file:
|
|
633
|
-
continue
|
|
634
|
-
|
|
635
|
-
corner_pex_template = utils.get_file_template(pex_source_file)
|
|
636
|
-
pex_template = utils.get_file_template('pex.tcl',
|
|
637
|
-
root=os.path.join(os.path.dirname(__file__),
|
|
638
|
-
'templates'))
|
|
639
|
-
|
|
640
|
-
if not pex_template:
|
|
641
|
-
continue
|
|
642
|
-
|
|
643
|
-
if constraint is None:
|
|
644
|
-
constraint = "default"
|
|
645
|
-
corner_specification = ""
|
|
646
|
-
else:
|
|
647
|
-
corner_specification = f"-corner {constraint}"
|
|
477
|
+
for key in (['pdk', pdkname, 'var', 'openroad', 'pin_layer_horizontal', stackup],
|
|
478
|
+
['pdk', pdkname, 'var', 'openroad', 'pin_layer_vertical', stackup]):
|
|
479
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key),
|
|
480
|
+
step=step, index=index)
|
|
648
481
|
|
|
649
|
-
f.write(pex_template.render(
|
|
650
|
-
constraint=constraint,
|
|
651
|
-
pexcorner=pexcorner,
|
|
652
|
-
source=pex_source_file,
|
|
653
|
-
pex=corner_pex_template.render({"corner": corner_specification})
|
|
654
|
-
))
|
|
655
|
-
f.write('\n')
|
|
656
482
|
|
|
483
|
+
def define_pdn_params(chip):
|
|
484
|
+
step = chip.get('arg', 'step')
|
|
485
|
+
index = chip.get('arg', 'index')
|
|
486
|
+
tool, task = get_tool_task(chip, step, index)
|
|
657
487
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
set_tool_task_var(chip, param_key='ifp_tie_separation',
|
|
662
|
-
default_value='0',
|
|
663
|
-
schelp='maximum distance between tie high/low cells in microns')
|
|
664
|
-
set_tool_task_var(chip, param_key='ifp_snap_strategy',
|
|
665
|
-
default_value='site',
|
|
666
|
-
schelp='Snapping strategy to use when placing macros. '
|
|
667
|
-
'Allowed values: none, site, manufacturing_grid')
|
|
488
|
+
set_tool_task_var(chip, param_key='pdn_enable',
|
|
489
|
+
default_value='true',
|
|
490
|
+
schelp='true/false, when true enables power grid generation')
|
|
668
491
|
|
|
669
492
|
# Files
|
|
670
|
-
chip.set('tool', tool, 'task', task, 'file', '
|
|
671
|
-
'
|
|
493
|
+
chip.set('tool', tool, 'task', task, 'file', 'pdn_config',
|
|
494
|
+
'list of files to use for power grid generation',
|
|
672
495
|
field='help')
|
|
673
496
|
|
|
674
497
|
|
|
675
|
-
def
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
498
|
+
def define_pdn_files(chip):
|
|
499
|
+
step = chip.get('arg', 'step')
|
|
500
|
+
index = chip.get('arg', 'index')
|
|
501
|
+
tool, task = get_tool_task(chip, step, index)
|
|
679
502
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
chip.set('tool', tool, 'task', task, 'file', 'ppl_constraints',
|
|
683
|
-
'script constrain pin placement',
|
|
684
|
-
field='help')
|
|
503
|
+
targetlibs = get_libraries(chip, 'logic')
|
|
504
|
+
macrolibs = get_libraries(chip, 'macro')
|
|
685
505
|
|
|
506
|
+
for libvar, openroadvar in [('openroad_pdngen', 'pdn_config')]:
|
|
507
|
+
if chip.valid('tool', tool, 'task', task, 'file', openroadvar) and \
|
|
508
|
+
chip.get('tool', tool, 'task', task, 'file', openroadvar, step=step, index=index):
|
|
509
|
+
# value already set
|
|
510
|
+
continue
|
|
686
511
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
512
|
+
# copy from libs
|
|
513
|
+
for lib in targetlibs + macrolibs:
|
|
514
|
+
if chip.valid('library', lib, 'option', 'file', libvar):
|
|
515
|
+
for vfile in chip.find_files('library', lib, 'option', 'file', libvar):
|
|
516
|
+
chip.add('tool', tool, 'task', task, 'file', openroadvar, vfile,
|
|
517
|
+
step=step, index=index)
|
|
693
518
|
|
|
694
|
-
# Files
|
|
695
|
-
chip.set('tool', tool, 'task', task, 'file', 'pdn_config',
|
|
696
|
-
'list of files to use for power grid generation',
|
|
697
|
-
field='help')
|
|
698
519
|
|
|
520
|
+
def define_pad_params(chip):
|
|
521
|
+
step = chip.get('arg', 'step')
|
|
522
|
+
index = chip.get('arg', 'index')
|
|
523
|
+
tool, task = get_tool_task(chip, step, index)
|
|
699
524
|
|
|
700
|
-
def _define_pad_params(chip):
|
|
701
|
-
tool, task = get_tool_task(chip, chip.get('arg', 'step'),
|
|
702
|
-
chip.get('arg', 'index'))
|
|
703
525
|
chip.set('tool', tool, 'task', task, 'file', 'padring',
|
|
704
526
|
'script to generate a padring using ICeWall in OpenROAD',
|
|
705
527
|
field='help')
|
|
706
528
|
|
|
529
|
+
if chip.get('tool', tool, 'task', task, 'file', 'padring', step=step, index=index):
|
|
530
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
531
|
+
",".join(['tool', tool, 'task', task, 'file', 'padring']),
|
|
532
|
+
step=step, index=index)
|
|
533
|
+
|
|
707
534
|
|
|
708
|
-
def
|
|
535
|
+
def define_rsz_params(chip):
|
|
709
536
|
set_tool_task_var(chip, param_key='rsz_skip_setup_repair',
|
|
710
537
|
default_value=False,
|
|
711
538
|
schelp='skip setup timing repair')
|
|
@@ -745,8 +572,21 @@ def _define_rsz_params(chip):
|
|
|
745
572
|
default_value='100',
|
|
746
573
|
schelp='percentage of violating nets to attempt to repair (0 - 100)')
|
|
747
574
|
|
|
575
|
+
step = chip.get('arg', 'step')
|
|
576
|
+
index = chip.get('arg', 'index')
|
|
577
|
+
tool, task = get_tool_task(chip, step, index)
|
|
748
578
|
|
|
749
|
-
|
|
579
|
+
pdkname = chip.get('option', 'pdk')
|
|
580
|
+
stackup = chip.get('option', 'stackup')
|
|
581
|
+
|
|
582
|
+
# Set required keys
|
|
583
|
+
for key in (['pdk', pdkname, 'var', 'openroad', 'rclayer_signal', stackup],
|
|
584
|
+
['pdk', pdkname, 'var', 'openroad', 'rclayer_clock', stackup]):
|
|
585
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key),
|
|
586
|
+
step=step, index=index)
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def define_gpl_params(chip):
|
|
750
590
|
set_tool_task_var(chip, param_key='place_density',
|
|
751
591
|
require=['key'],
|
|
752
592
|
schelp='global placement density (0.0 - 1.0)')
|
|
@@ -772,7 +612,7 @@ def _define_gpl_params(chip):
|
|
|
772
612
|
'considering the impact of the pin placements')
|
|
773
613
|
|
|
774
614
|
|
|
775
|
-
def
|
|
615
|
+
def define_dpo_params(chip):
|
|
776
616
|
set_tool_task_var(chip, param_key='dpo_enable',
|
|
777
617
|
default_value='true',
|
|
778
618
|
schelp='true/false, when true the detailed placement optimization '
|
|
@@ -783,7 +623,7 @@ def _define_dpo_params(chip):
|
|
|
783
623
|
'0 will result in the tool default maximum displacement')
|
|
784
624
|
|
|
785
625
|
|
|
786
|
-
def
|
|
626
|
+
def define_dpl_params(chip):
|
|
787
627
|
set_tool_task_var(chip, param_key='pad_detail_place',
|
|
788
628
|
require=['key'],
|
|
789
629
|
schelp='detailed placement cell padding in number of sites')
|
|
@@ -801,15 +641,7 @@ def _define_dpl_params(chip):
|
|
|
801
641
|
schelp='true/false, use decap fillers along with non-decap fillers')
|
|
802
642
|
|
|
803
643
|
|
|
804
|
-
def
|
|
805
|
-
step = chip.get('arg', 'step')
|
|
806
|
-
index = chip.get('arg', 'index')
|
|
807
|
-
mainlib = get_mainlib(chip)
|
|
808
|
-
|
|
809
|
-
set_tool_task_var(chip, param_key='cts_clock_buffer',
|
|
810
|
-
default_value=chip.get('library', mainlib, 'asic', 'cells', 'clkbuf',
|
|
811
|
-
step=step, index=index)[-1],
|
|
812
|
-
schelp='buffer to use during clock tree synthesis')
|
|
644
|
+
def define_cts_params(chip):
|
|
813
645
|
set_tool_task_var(chip, param_key='cts_distance_between_buffers',
|
|
814
646
|
default_value='100',
|
|
815
647
|
schelp='maximum distance between buffers during clock tree synthesis '
|
|
@@ -828,30 +660,16 @@ def _define_cts_params(chip):
|
|
|
828
660
|
schelp='make clock tree synthesis aware of obstructions')
|
|
829
661
|
|
|
830
662
|
|
|
831
|
-
def
|
|
663
|
+
def define_grt_params(chip, load_all=False):
|
|
832
664
|
pdkname = chip.get('option', 'pdk')
|
|
833
665
|
stackup = chip.get('option', 'stackup')
|
|
834
666
|
|
|
835
667
|
pdk_min_layer = chip.get('pdk', pdkname, 'minlayer', stackup)
|
|
836
668
|
pdk_max_layer = chip.get('pdk', pdkname, 'maxlayer', stackup)
|
|
837
669
|
|
|
838
|
-
set_tool_task_var(chip, param_key='
|
|
839
|
-
default_value='
|
|
840
|
-
schelp='true/false, when true
|
|
841
|
-
set_tool_task_var(chip, param_key='grt_overflow_iter',
|
|
842
|
-
default_value='100',
|
|
843
|
-
schelp='maximum number of iterations to use in global routing when '
|
|
844
|
-
'attempting to solve overflow')
|
|
845
|
-
set_tool_task_var(chip, param_key='grt_macro_extension',
|
|
846
|
-
default_value='0',
|
|
847
|
-
schelp='macro extension distance in number of gcells, this can be useful '
|
|
848
|
-
'when the detailed router needs additional space to avoid DRCs')
|
|
849
|
-
set_tool_task_var(chip, param_key='grt_allow_congestion',
|
|
850
|
-
default_value='false',
|
|
851
|
-
schelp='true/false, when true allow global routing to finish with congestion')
|
|
852
|
-
set_tool_task_var(chip, param_key='grt_allow_overflow',
|
|
853
|
-
default_value='false',
|
|
854
|
-
schelp='true/false, when true allow global routing to finish with overflow')
|
|
670
|
+
set_tool_task_var(chip, param_key='grt_setup',
|
|
671
|
+
default_value='true',
|
|
672
|
+
schelp='true/false, when true global route is setup')
|
|
855
673
|
set_tool_task_var(chip, param_key='grt_signal_min_layer',
|
|
856
674
|
default_value=pdk_min_layer,
|
|
857
675
|
schelp='minimum layer to use for global routing of signals')
|
|
@@ -864,9 +682,30 @@ def _define_grt_params(chip):
|
|
|
864
682
|
set_tool_task_var(chip, param_key='grt_clock_max_layer',
|
|
865
683
|
default_value=pdk_max_layer,
|
|
866
684
|
schelp='maximum layer to use for global routing of clock nets')
|
|
685
|
+
set_tool_task_var(chip, param_key='grt_macro_extension',
|
|
686
|
+
default_value='0',
|
|
687
|
+
schelp='macro extension distance in number of gcells, this can be useful '
|
|
688
|
+
'when the detailed router needs additional space to avoid DRCs')
|
|
867
689
|
|
|
868
|
-
|
|
869
|
-
|
|
690
|
+
if load_all:
|
|
691
|
+
set_tool_task_var(chip, param_key='grt_use_pin_access',
|
|
692
|
+
default_value='false',
|
|
693
|
+
schelp='true/false, when true perform pin access before global routing')
|
|
694
|
+
set_tool_task_var(chip, param_key='grt_overflow_iter',
|
|
695
|
+
default_value='100',
|
|
696
|
+
schelp='maximum number of iterations to use in global routing when '
|
|
697
|
+
'attempting to solve overflow')
|
|
698
|
+
set_tool_task_var(chip, param_key='grt_allow_congestion',
|
|
699
|
+
default_value='false',
|
|
700
|
+
schelp='true/false, when true allow global routing to finish '
|
|
701
|
+
'with congestion')
|
|
702
|
+
set_tool_task_var(chip, param_key='grt_allow_overflow',
|
|
703
|
+
default_value='false',
|
|
704
|
+
schelp='true/false, when true allow global routing to finish '
|
|
705
|
+
'with overflow')
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def define_ant_params(chip):
|
|
870
709
|
set_tool_task_var(chip, param_key='ant_iterations',
|
|
871
710
|
default_value='3',
|
|
872
711
|
schelp='maximum number of repair iterations to use during antenna repairs')
|
|
@@ -881,7 +720,7 @@ def _define_ant_params(chip):
|
|
|
881
720
|
schelp='true/false, flag to indicate whether to repair antenna violations')
|
|
882
721
|
|
|
883
722
|
|
|
884
|
-
def
|
|
723
|
+
def define_drt_params(chip):
|
|
885
724
|
set_tool_task_var(chip, param_key='drt_disable_via_gen',
|
|
886
725
|
default_value='false',
|
|
887
726
|
schelp='true/false, when true turns off via generation in detailed router '
|
|
@@ -908,7 +747,7 @@ def _define_drt_params(chip):
|
|
|
908
747
|
'what the tech lef specifies')
|
|
909
748
|
|
|
910
749
|
|
|
911
|
-
def
|
|
750
|
+
def define_sta_params(chip):
|
|
912
751
|
step = chip.get('arg', 'step')
|
|
913
752
|
index = chip.get('arg', 'index')
|
|
914
753
|
tool, task = get_tool_task(chip, step, index)
|
|
@@ -925,17 +764,22 @@ def _define_sta_params(chip):
|
|
|
925
764
|
|
|
926
765
|
chip.set('tool', tool, 'task', task, 'var', 'power_corner', get_power_corner(chip),
|
|
927
766
|
step=step, index=index, clobber=False)
|
|
767
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
768
|
+
','.join(['tool', tool, 'task', task, 'var', 'power_corner']),
|
|
769
|
+
step=step, index=index)
|
|
928
770
|
chip.set('tool', tool, 'task', task, 'var', 'power_corner',
|
|
929
771
|
'corner to use for power analysis',
|
|
930
772
|
field='help')
|
|
931
773
|
|
|
774
|
+
add_common_file(chip, 'opensta_generic_sdc', 'sdc/sc_constraints.sdc')
|
|
775
|
+
|
|
932
776
|
|
|
933
|
-
def
|
|
777
|
+
def define_sdc_params(chip):
|
|
934
778
|
set_tool_task_var(chip, param_key='sdc_buffer',
|
|
935
779
|
schelp='buffer cell to use when auto generating timing constraints')
|
|
936
780
|
|
|
937
781
|
|
|
938
|
-
def
|
|
782
|
+
def define_psm_params(chip):
|
|
939
783
|
step = chip.get('arg', 'step')
|
|
940
784
|
index = chip.get('arg', 'index')
|
|
941
785
|
tool, task = get_tool_task(chip, step, index)
|
|
@@ -949,14 +793,14 @@ def _define_psm_params(chip):
|
|
|
949
793
|
field='help')
|
|
950
794
|
|
|
951
795
|
|
|
952
|
-
def
|
|
796
|
+
def define_fin_params(chip):
|
|
953
797
|
set_tool_task_var(chip, param_key='fin_add_fill',
|
|
954
798
|
default_value='true',
|
|
955
799
|
schelp='true/false, when true enables adding fill, '
|
|
956
800
|
'if enabled by the PDK, to the design')
|
|
957
801
|
|
|
958
802
|
|
|
959
|
-
def
|
|
803
|
+
def define_mpl_params(chip):
|
|
960
804
|
set_tool_task_var(chip, param_key='macro_place_halo',
|
|
961
805
|
require=['key'],
|
|
962
806
|
schelp='macro halo to use when performing automated '
|
|
@@ -1016,16 +860,11 @@ def _define_mpl_params(chip):
|
|
|
1016
860
|
schelp='Weight for macro blockage, or the overlapping instances of the macro')
|
|
1017
861
|
|
|
1018
862
|
|
|
1019
|
-
def
|
|
863
|
+
def define_ord_params(chip):
|
|
1020
864
|
step = chip.get('arg', 'step')
|
|
1021
865
|
index = chip.get('arg', 'index')
|
|
1022
866
|
tool, task = get_tool_task(chip, step, index)
|
|
1023
867
|
|
|
1024
|
-
# Parameters without pdk/lib dependencies
|
|
1025
|
-
chip.set('tool', tool, 'task', task, 'var', 'debug_level',
|
|
1026
|
-
'list of "tool key level" to enable debugging of OpenROAD',
|
|
1027
|
-
field='help')
|
|
1028
|
-
|
|
1029
868
|
chip.set('tool', tool, 'task', task, 'file', 'global_connect',
|
|
1030
869
|
'list of files to use for specifying global connections',
|
|
1031
870
|
field='help')
|
|
@@ -1056,7 +895,28 @@ def _define_ord_params(chip):
|
|
|
1056
895
|
schelp='number of Y bins to use for heatmap image generation')
|
|
1057
896
|
|
|
1058
897
|
|
|
1059
|
-
def
|
|
898
|
+
def define_ord_files(chip):
|
|
899
|
+
step = chip.get('arg', 'step')
|
|
900
|
+
index = chip.get('arg', 'index')
|
|
901
|
+
tool, task = get_tool_task(chip, step, index)
|
|
902
|
+
targetlibs = get_libraries(chip, 'logic')
|
|
903
|
+
macrolibs = get_libraries(chip, 'macro')
|
|
904
|
+
|
|
905
|
+
for libvar, openroadvar in [('openroad_global_connect', 'global_connect')]:
|
|
906
|
+
if chip.valid('tool', tool, 'task', task, 'file', openroadvar) and \
|
|
907
|
+
chip.get('tool', tool, 'task', task, 'file', openroadvar, step=step, index=index):
|
|
908
|
+
# value already set
|
|
909
|
+
continue
|
|
910
|
+
|
|
911
|
+
# copy from libs
|
|
912
|
+
for lib in targetlibs + macrolibs:
|
|
913
|
+
if chip.valid('library', lib, 'option', 'file', libvar):
|
|
914
|
+
for vfile in chip.find_files('library', lib, 'option', 'file', libvar):
|
|
915
|
+
chip.add('tool', tool, 'task', task, 'file', openroadvar, vfile,
|
|
916
|
+
step=step, index=index)
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
def define_pex_params(chip):
|
|
1060
920
|
step = chip.get('arg', 'step')
|
|
1061
921
|
index = chip.get('arg', 'index')
|
|
1062
922
|
tool, task = get_tool_task(chip, step, index)
|
|
@@ -1073,11 +933,30 @@ def _define_pex_params(chip):
|
|
|
1073
933
|
field='help')
|
|
1074
934
|
|
|
1075
935
|
|
|
1076
|
-
def
|
|
936
|
+
def set_reports(chip, reports):
|
|
1077
937
|
step = chip.get('arg', 'step')
|
|
1078
938
|
index = chip.get('arg', 'index')
|
|
1079
939
|
tool, task = get_tool_task(chip, step, index)
|
|
1080
940
|
|
|
941
|
+
# supported reports
|
|
942
|
+
supported = (
|
|
943
|
+
"setup",
|
|
944
|
+
"hold",
|
|
945
|
+
"unconstrained",
|
|
946
|
+
"clock_skew",
|
|
947
|
+
"drv_violations",
|
|
948
|
+
"fmax",
|
|
949
|
+
"power",
|
|
950
|
+
"check_setup",
|
|
951
|
+
"placement_density",
|
|
952
|
+
"routing_congestion",
|
|
953
|
+
"power_density",
|
|
954
|
+
"ir_drop",
|
|
955
|
+
"clock_placement",
|
|
956
|
+
"clock_trees",
|
|
957
|
+
"optimization_placement"
|
|
958
|
+
)
|
|
959
|
+
|
|
1081
960
|
chip.set('tool', tool, 'task', task, 'var', 'reports',
|
|
1082
961
|
'list of reports and images to generate',
|
|
1083
962
|
field='help')
|
|
@@ -1097,6 +976,8 @@ def _set_reports(chip, reports):
|
|
|
1097
976
|
return True
|
|
1098
977
|
|
|
1099
978
|
for report in reports:
|
|
979
|
+
if report not in supported:
|
|
980
|
+
raise ValueError(f'{report} is not supported')
|
|
1100
981
|
if check_enabled(report):
|
|
1101
982
|
chip.add('tool', tool, 'task', task, 'var', 'reports', report,
|
|
1102
983
|
step=step, index=index)
|
|
@@ -1142,8 +1023,118 @@ def set_pnr_outputs(chip):
|
|
|
1142
1023
|
chip.add('tool', tool, 'task', task, 'output', design + '.odb', step=step, index=index)
|
|
1143
1024
|
|
|
1144
1025
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1026
|
+
def get_library_timing_keypaths(chip, lib):
|
|
1027
|
+
step = chip.get('arg', 'step')
|
|
1028
|
+
index = chip.get('arg', 'index')
|
|
1029
|
+
|
|
1030
|
+
delaymodel = chip.get('asic', 'delaymodel', step=step, index=index)
|
|
1031
|
+
keypaths = {}
|
|
1032
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
1033
|
+
corners = chip.get('constraint', 'timing', constraint, 'libcorner', step=step, index=index)
|
|
1034
|
+
for corner in corners:
|
|
1035
|
+
if chip.valid('library', lib, 'output', corner, delaymodel):
|
|
1036
|
+
keypaths[constraint] = ('library', lib, 'output', corner, delaymodel)
|
|
1037
|
+
|
|
1038
|
+
if constraint not in keypaths:
|
|
1039
|
+
keypaths[constraint] = ('library', lib, 'output', corners[0], delaymodel)
|
|
1040
|
+
return keypaths
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
def get_pex_corners(chip):
|
|
1044
|
+
step = chip.get('arg', 'step')
|
|
1045
|
+
index = chip.get('arg', 'index')
|
|
1046
|
+
|
|
1047
|
+
corners = set()
|
|
1048
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
1049
|
+
pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
|
|
1050
|
+
step=step, index=index)
|
|
1051
|
+
if pexcorner:
|
|
1052
|
+
corners.add(pexcorner)
|
|
1053
|
+
|
|
1054
|
+
return list(corners)
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
def _get_constraint_by_check(chip, check):
|
|
1058
|
+
step = chip.get('arg', 'step')
|
|
1059
|
+
index = chip.get('arg', 'index')
|
|
1060
|
+
|
|
1061
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
1062
|
+
if check in chip.get('constraint', 'timing', constraint, 'check',
|
|
1063
|
+
step=step, index=index):
|
|
1064
|
+
return constraint
|
|
1065
|
+
|
|
1066
|
+
# if not specified, just pick the first constraint available
|
|
1067
|
+
return chip.getkeys('constraint', 'timing')[0]
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
def get_power_corner(chip):
|
|
1071
|
+
return _get_constraint_by_check(chip, "power")
|
|
1072
|
+
|
|
1147
1073
|
|
|
1148
|
-
|
|
1149
|
-
chip
|
|
1074
|
+
def get_setup_corner(chip):
|
|
1075
|
+
return _get_constraint_by_check(chip, "setup")
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
def build_pex_corners(chip):
|
|
1079
|
+
step = chip.get('arg', 'step')
|
|
1080
|
+
index = chip.get('arg', 'index')
|
|
1081
|
+
tool, task = get_tool_task(chip, step, index)
|
|
1082
|
+
|
|
1083
|
+
pdkname = chip.get('option', 'pdk')
|
|
1084
|
+
stackup = chip.get('option', 'stackup')
|
|
1085
|
+
|
|
1086
|
+
corners = {}
|
|
1087
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
1088
|
+
pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
|
|
1089
|
+
step=step, index=index)
|
|
1090
|
+
|
|
1091
|
+
if not pexcorner:
|
|
1092
|
+
continue
|
|
1093
|
+
corners[constraint] = pexcorner
|
|
1094
|
+
|
|
1095
|
+
default_corner = get_setup_corner(chip)
|
|
1096
|
+
if default_corner in corners:
|
|
1097
|
+
corners[None] = corners[default_corner]
|
|
1098
|
+
|
|
1099
|
+
chip.set('tool', tool, 'task', task, 'file', 'parasitics',
|
|
1100
|
+
os.path.join(chip.getworkdir(step=step, index=index),
|
|
1101
|
+
'inputs',
|
|
1102
|
+
'sc_parasitics.tcl'),
|
|
1103
|
+
step=step, index=index, clobber=True)
|
|
1104
|
+
|
|
1105
|
+
with open(chip.get('tool', tool, 'task', task, 'file', 'parasitics',
|
|
1106
|
+
step=step, index=index)[0], 'w') as f:
|
|
1107
|
+
for constraint, pexcorner in corners.items():
|
|
1108
|
+
if chip.valid('pdk', pdkname, 'pexmodel', tool, stackup, pexcorner):
|
|
1109
|
+
pex_source_file = chip.find_files(
|
|
1110
|
+
'pdk',
|
|
1111
|
+
pdkname,
|
|
1112
|
+
'pexmodel',
|
|
1113
|
+
tool,
|
|
1114
|
+
stackup,
|
|
1115
|
+
pexcorner)[0]
|
|
1116
|
+
if not pex_source_file:
|
|
1117
|
+
continue
|
|
1118
|
+
|
|
1119
|
+
corner_pex_template = utils.get_file_template(pex_source_file)
|
|
1120
|
+
pex_template = utils.get_file_template(
|
|
1121
|
+
'pex.tcl',
|
|
1122
|
+
root=os.path.join(os.path.dirname(__file__),
|
|
1123
|
+
'templates'))
|
|
1124
|
+
|
|
1125
|
+
if not pex_template:
|
|
1126
|
+
continue
|
|
1127
|
+
|
|
1128
|
+
if constraint is None:
|
|
1129
|
+
constraint = "default"
|
|
1130
|
+
corner_specification = ""
|
|
1131
|
+
else:
|
|
1132
|
+
corner_specification = f"-corner {constraint}"
|
|
1133
|
+
|
|
1134
|
+
f.write(pex_template.render(
|
|
1135
|
+
constraint=constraint,
|
|
1136
|
+
pexcorner=pexcorner,
|
|
1137
|
+
source=pex_source_file,
|
|
1138
|
+
pex=corner_pex_template.render({"corner": corner_specification})
|
|
1139
|
+
))
|
|
1140
|
+
f.write('\n')
|