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.
Files changed (109) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_remote.py +15 -14
  3. siliconcompiler/apps/sc_show.py +5 -5
  4. siliconcompiler/apps/utils/replay.py +136 -0
  5. siliconcompiler/core.py +14 -12
  6. siliconcompiler/flows/_common.py +11 -13
  7. siliconcompiler/flows/asicflow.py +83 -42
  8. siliconcompiler/remote/__init__.py +11 -0
  9. siliconcompiler/remote/client.py +753 -815
  10. siliconcompiler/report/report.py +2 -0
  11. siliconcompiler/report/summary_table.py +1 -1
  12. siliconcompiler/scheduler/__init__.py +51 -9
  13. siliconcompiler/schema/schema_cfg.py +15 -3
  14. siliconcompiler/schema/schema_obj.py +16 -0
  15. siliconcompiler/sphinx_ext/dynamicgen.py +4 -3
  16. siliconcompiler/targets/gf180_demo.py +3 -3
  17. siliconcompiler/templates/replay/requirements.txt +6 -0
  18. siliconcompiler/templates/replay/run.py.j2 +22 -0
  19. siliconcompiler/templates/replay/setup.sh +17 -0
  20. siliconcompiler/tools/_common/__init__.py +15 -1
  21. siliconcompiler/tools/_common/asic.py +10 -3
  22. siliconcompiler/tools/builtin/concatenate.py +1 -1
  23. siliconcompiler/tools/openroad/__init__.py +103 -0
  24. siliconcompiler/tools/openroad/{openroad.py → _apr.py} +413 -422
  25. siliconcompiler/tools/openroad/antenna_repair.py +78 -0
  26. siliconcompiler/tools/openroad/clock_tree_synthesis.py +64 -0
  27. siliconcompiler/tools/openroad/detailed_placement.py +59 -0
  28. siliconcompiler/tools/openroad/detailed_route.py +62 -0
  29. siliconcompiler/tools/openroad/endcap_tapcell_insertion.py +52 -0
  30. siliconcompiler/tools/openroad/fillercell_insertion.py +58 -0
  31. siliconcompiler/tools/openroad/{dfm.py → fillmetal_insertion.py} +35 -19
  32. siliconcompiler/tools/openroad/global_placement.py +58 -0
  33. siliconcompiler/tools/openroad/global_route.py +63 -0
  34. siliconcompiler/tools/openroad/init_floorplan.py +103 -0
  35. siliconcompiler/tools/openroad/macro_placement.py +65 -0
  36. siliconcompiler/tools/openroad/metrics.py +23 -8
  37. siliconcompiler/tools/openroad/pin_placement.py +56 -0
  38. siliconcompiler/tools/openroad/power_grid.py +65 -0
  39. siliconcompiler/tools/openroad/rcx_bench.py +7 -4
  40. siliconcompiler/tools/openroad/rcx_extract.py +2 -1
  41. siliconcompiler/tools/openroad/rdlroute.py +4 -4
  42. siliconcompiler/tools/openroad/repair_design.py +59 -0
  43. siliconcompiler/tools/openroad/repair_timing.py +63 -0
  44. siliconcompiler/tools/openroad/screenshot.py +9 -20
  45. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +44 -0
  46. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +95 -0
  47. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +51 -0
  48. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +62 -0
  49. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +41 -0
  50. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +71 -0
  51. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +55 -0
  52. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +27 -0
  53. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +36 -0
  54. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +26 -0
  55. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +61 -0
  56. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +333 -0
  57. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +123 -0
  58. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +22 -0
  59. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +41 -0
  60. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +60 -0
  61. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +68 -0
  62. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +83 -0
  63. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +125 -0
  64. siliconcompiler/tools/openroad/scripts/common/debugging.tcl +28 -0
  65. siliconcompiler/tools/openroad/scripts/common/procs.tcl +675 -0
  66. siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +59 -0
  67. siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +20 -0
  68. siliconcompiler/tools/openroad/scripts/common/read_timing_constraints.tcl +16 -0
  69. siliconcompiler/tools/openroad/scripts/common/reports.tcl +180 -0
  70. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +18 -0
  71. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +395 -0
  72. siliconcompiler/tools/openroad/scripts/{sc_rcx_bench.tcl → rcx/sc_rcx_bench.tcl} +5 -5
  73. siliconcompiler/tools/openroad/scripts/{sc_rcx_extract.tcl → rcx/sc_rcx_extract.tcl} +0 -0
  74. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +5 -16
  75. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +51 -51
  76. siliconcompiler/tools/openroad/scripts/sc_show.tcl +105 -0
  77. siliconcompiler/tools/openroad/show.py +28 -23
  78. siliconcompiler/tools/openroad/{export.py → write_data.py} +31 -26
  79. siliconcompiler/tools/opensta/__init__.py +1 -1
  80. siliconcompiler/tools/yosys/syn_asic.py +7 -0
  81. siliconcompiler/tools/yosys/syn_asic.tcl +27 -6
  82. siliconcompiler/tools/yosys/syn_fpga.tcl +26 -18
  83. siliconcompiler/toolscripts/_tools.json +4 -4
  84. {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/METADATA +14 -12
  85. {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/RECORD +90 -63
  86. siliconcompiler/tools/openroad/cts.py +0 -45
  87. siliconcompiler/tools/openroad/floorplan.py +0 -75
  88. siliconcompiler/tools/openroad/physyn.py +0 -27
  89. siliconcompiler/tools/openroad/place.py +0 -41
  90. siliconcompiler/tools/openroad/route.py +0 -45
  91. siliconcompiler/tools/openroad/scripts/__init__.py +0 -0
  92. siliconcompiler/tools/openroad/scripts/sc_apr.tcl +0 -514
  93. siliconcompiler/tools/openroad/scripts/sc_cts.tcl +0 -68
  94. siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +0 -22
  95. siliconcompiler/tools/openroad/scripts/sc_export.tcl +0 -100
  96. siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +0 -456
  97. siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +0 -1
  98. siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +0 -6
  99. siliconcompiler/tools/openroad/scripts/sc_place.tcl +0 -84
  100. siliconcompiler/tools/openroad/scripts/sc_procs.tcl +0 -494
  101. siliconcompiler/tools/openroad/scripts/sc_report.tcl +0 -189
  102. siliconcompiler/tools/openroad/scripts/sc_route.tcl +0 -143
  103. siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +0 -18
  104. siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +0 -393
  105. /siliconcompiler/tools/openroad/scripts/{sc_write.tcl → common/write_data.tcl} +0 -0
  106. {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/LICENSE +0 -0
  107. {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/WHEEL +0 -0
  108. {siliconcompiler-0.28.9.dist-info → siliconcompiler-0.29.0.dist-info}/entry_points.txt +0 -0
  109. {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.targets import asap7_demo
9
+ from siliconcompiler.tools.openroad import setup as tool_setup
23
10
 
24
11
 
25
- ####################################################################
26
- # Make Docs
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, 'exe', tool)
41
- chip.set('tool', tool, 'vswitch', '-version')
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.logger.error(f'{delaymodel} delay model is not supported by {tool}, only nldm')
31
+ chip.error(f'{delaymodel} delay model is not supported by {tool}, only nldm')
101
32
 
102
- if stackup and targetlibs:
103
- # Note: only one footprint supported in mainlib
104
- chip.add('tool', tool, 'task', task, 'require',
105
- ",".join(['asic', 'logiclib']),
106
- step=step, index=index)
107
- chip.add('tool', tool, 'task', task, 'require',
108
- ",".join(['option', 'stackup']),
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
- chip.add('tool', tool, 'task', task, 'require',
111
- ",".join(['library', mainlib, 'asic', 'site', libtype]),
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(['pdk', pdkname, 'aprtech', 'openroad', stackup, libtype, 'lef']),
63
+ ",".join(['library', lib, 'output', stackup, 'lef']),
115
64
  step=step, index=index)
116
-
117
- for lib in targetlibs:
118
- for timing_key in get_library_timing_keypaths(chip, lib).values():
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(key),
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
- add_common_file(chip, 'opensta_generic_sdc', 'sdc/sc_constraints.sdc')
175
-
176
- # basic warning and error grep check on logfile
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": ["timing/total_negative_slack.rpt"],
260
- "setupslack": ["timing/worst_slack.setup.rpt", "timing/setup.rpt", "timing/setup.topN.rpt"],
261
- "setupskew": ["timing/skew.setup.rpt",
262
- "timing/worst_slack.setup.rpt",
263
- "timing/setup.rpt",
264
- "timing/setup.topN.rpt"],
265
- "setuppaths": ["timing/setup.topN.rpt"],
266
- "holdslack": ["timing/worst_slack.hold.rpt", "timing/hold.rpt", "timing/hold.topN.rpt"],
267
- "holdskew": ["timing/skew.hold.rpt",
268
- "timing/worst_slack.hold.rpt",
269
- "timing/hold.rpt",
270
- "timing/hold.topN.rpt"],
271
- "holdpaths": ["timing/hold.topN.rpt"],
272
- "unconstrained": ["timing/unconstrained.rpt", "timing/unconstrained.topN.rpt"],
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": ["timing/drv_violators.rpt",
279
- "floating_nets.rpt",
280
- f"{chip.design}_antenna.rpt",
281
- f"{chip.design}_antenna_post_repair.rpt"],
282
- "drcs": [f"{chip.design}_drc.rpt",
283
- f"markers/{chip.design}.drc.rpt",
284
- f"markers/{chip.design}.drc.json",
285
- f"images/markers/{chip.design}.drc.png"],
286
- "utilization": ["images/heatmap/placement_density.png"],
287
- "wirelength": [f"images/{chip.design}.routing.png"]
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 [('time', 'run__flow__platform__time_units'),
314
- ('capacitance', 'run__flow__platform__capacitance_units'),
315
- ('resistance', 'run__flow__platform__resistance_units'),
316
- ('volt', 'run__flow__platform__voltage_units'),
317
- ('amp', 'run__flow__platform__current_units'),
318
- ('power', 'run__flow__platform__power_units'),
319
- ('distance', 'run__flow__platform__distance_units')]:
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 ['sc__metric__timing__drv__max_slew',
418
- 'sc__metric__timing__drv__max_cap',
419
- 'sc__metric__timing__drv__max_fanout',
420
- 'sc__metric__antenna__violating__nets',
421
- 'sc__metric__antenna__violating__pins']:
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
- delaymodel = chip.get('asic', 'delaymodel', step=step, index=index)
550
- keypaths = {}
551
- for constraint in chip.getkeys('constraint', 'timing'):
552
- corners = chip.get('constraint', 'timing', constraint, 'libcorner', step=step, index=index)
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
- corners = set()
568
- for constraint in chip.getkeys('constraint', 'timing'):
569
- pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
570
- step=step, index=index)
571
- if pexcorner:
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
- return list(corners)
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 get_constraint_by_check(chip, check):
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
- for constraint in chip.getkeys('constraint', 'timing'):
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
- corners = {}
607
- for constraint in chip.getkeys('constraint', 'timing'):
608
- pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
609
- step=step, index=index)
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
- def _define_ifp_params(chip):
659
- tool, task = get_tool_task(chip, chip.get('arg', 'step'),
660
- chip.get('arg', 'index'))
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', 'ifp_tapcell',
671
- 'tap cell insertion script',
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 _define_ppl_params(chip):
676
- set_tool_task_var(chip, param_key='ppl_arguments',
677
- default_value=[],
678
- schelp='additional arguments to pass along to the pin placer.')
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
- tool, task = get_tool_task(chip, chip.get('arg', 'step'),
681
- chip.get('arg', 'index'))
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
- def _define_pdn_params(chip):
688
- tool, task = get_tool_task(chip, chip.get('arg', 'step'),
689
- chip.get('arg', 'index'))
690
- set_tool_task_var(chip, param_key='pdn_enable',
691
- default_value='true',
692
- schelp='true/false, when true enables power grid generation')
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 _define_rsz_params(chip):
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
- def _define_gpl_params(chip):
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 _define_dpo_params(chip):
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 _define_dpl_params(chip):
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 _define_cts_params(chip):
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 _define_grt_params(chip):
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='grt_use_pin_access',
839
- default_value='false',
840
- schelp='true/false, when true perform pin access before global routing')
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
- def _define_ant_params(chip):
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 _define_drt_params(chip):
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 _define_sta_params(chip):
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 _define_sdc_params(chip):
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 _define_psm_params(chip):
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 _define_fin_params(chip):
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 _define_mpl_params(chip):
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 _define_ord_params(chip):
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 _define_pex_params(chip):
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 _set_reports(chip, reports):
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
- if __name__ == "__main__":
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
- chip = make_docs()
1149
- chip.write_manifest("openroad.json")
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')