siliconcompiler 0.35.4__py3-none-any.whl → 0.36.1__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 (89) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/constraints/__init__.py +4 -1
  3. siliconcompiler/constraints/asic_timing.py +230 -38
  4. siliconcompiler/constraints/fpga_timing.py +209 -14
  5. siliconcompiler/constraints/timing_mode.py +82 -0
  6. siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
  7. siliconcompiler/flowgraph.py +95 -42
  8. siliconcompiler/flows/generate_openroad_rcx.py +2 -2
  9. siliconcompiler/flows/highresscreenshotflow.py +37 -0
  10. siliconcompiler/library.py +2 -1
  11. siliconcompiler/package/__init__.py +39 -45
  12. siliconcompiler/project.py +4 -1
  13. siliconcompiler/scheduler/scheduler.py +64 -35
  14. siliconcompiler/scheduler/schedulernode.py +5 -2
  15. siliconcompiler/scheduler/slurm.py +7 -6
  16. siliconcompiler/scheduler/taskscheduler.py +19 -16
  17. siliconcompiler/schema/_metadata.py +1 -1
  18. siliconcompiler/schema/namedschema.py +2 -4
  19. siliconcompiler/schema_support/cmdlineschema.py +0 -3
  20. siliconcompiler/schema_support/dependencyschema.py +0 -6
  21. siliconcompiler/schema_support/record.py +4 -3
  22. siliconcompiler/tool.py +58 -27
  23. siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
  24. siliconcompiler/tools/chisel/convert.py +44 -0
  25. siliconcompiler/tools/ghdl/convert.py +37 -2
  26. siliconcompiler/tools/icarus/compile.py +14 -0
  27. siliconcompiler/tools/keplerformal/__init__.py +7 -0
  28. siliconcompiler/tools/keplerformal/lec.py +112 -0
  29. siliconcompiler/tools/klayout/drc.py +14 -0
  30. siliconcompiler/tools/klayout/export.py +40 -0
  31. siliconcompiler/tools/klayout/operations.py +40 -0
  32. siliconcompiler/tools/klayout/screenshot.py +66 -1
  33. siliconcompiler/tools/klayout/scripts/klayout_export.py +10 -40
  34. siliconcompiler/tools/klayout/scripts/klayout_show.py +4 -4
  35. siliconcompiler/tools/klayout/scripts/klayout_utils.py +13 -1
  36. siliconcompiler/tools/montage/tile.py +26 -12
  37. siliconcompiler/tools/openroad/__init__.py +11 -0
  38. siliconcompiler/tools/openroad/_apr.py +780 -11
  39. siliconcompiler/tools/openroad/antenna_repair.py +26 -0
  40. siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -0
  41. siliconcompiler/tools/openroad/global_placement.py +67 -0
  42. siliconcompiler/tools/openroad/global_route.py +15 -0
  43. siliconcompiler/tools/openroad/init_floorplan.py +19 -2
  44. siliconcompiler/tools/openroad/macro_placement.py +252 -0
  45. siliconcompiler/tools/openroad/power_grid.py +43 -0
  46. siliconcompiler/tools/openroad/power_grid_analysis.py +1 -1
  47. siliconcompiler/tools/openroad/rcx_bench.py +28 -0
  48. siliconcompiler/tools/openroad/rcx_extract.py +14 -0
  49. siliconcompiler/tools/openroad/rdlroute.py +14 -0
  50. siliconcompiler/tools/openroad/repair_design.py +41 -0
  51. siliconcompiler/tools/openroad/repair_timing.py +54 -0
  52. siliconcompiler/tools/openroad/screenshot.py +31 -1
  53. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +8 -0
  54. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +54 -15
  55. siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +6 -4
  56. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +4 -4
  57. siliconcompiler/tools/openroad/scripts/common/procs.tcl +14 -5
  58. siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
  59. siliconcompiler/tools/openroad/scripts/common/reports.tcl +6 -3
  60. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
  61. siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
  62. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
  63. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
  64. siliconcompiler/tools/openroad/write_data.py +78 -2
  65. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
  66. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
  67. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +12 -14
  68. siliconcompiler/tools/opensta/timing.py +42 -3
  69. siliconcompiler/tools/slang/elaborate.py +16 -1
  70. siliconcompiler/tools/surelog/parse.py +54 -0
  71. siliconcompiler/tools/verilator/compile.py +120 -0
  72. siliconcompiler/tools/vivado/syn_fpga.py +27 -0
  73. siliconcompiler/tools/vpr/route.py +40 -0
  74. siliconcompiler/tools/xdm/convert.py +14 -0
  75. siliconcompiler/tools/xyce/simulate.py +26 -0
  76. siliconcompiler/tools/yosys/lec_asic.py +13 -0
  77. siliconcompiler/tools/yosys/syn_asic.py +332 -3
  78. siliconcompiler/tools/yosys/syn_fpga.py +32 -0
  79. siliconcompiler/toolscripts/_tools.json +9 -4
  80. siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
  81. siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
  82. siliconcompiler/utils/multiprocessing.py +11 -0
  83. siliconcompiler/utils/settings.py +70 -49
  84. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/METADATA +4 -4
  85. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/RECORD +89 -83
  86. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/WHEEL +0 -0
  87. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/entry_points.txt +0 -0
  88. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/licenses/LICENSE +0 -0
  89. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,9 @@ from siliconcompiler.tools.openroad import OpenROADTask
12
12
 
13
13
 
14
14
  class OpenROADSTAParameter(OpenROADTask):
15
+ """
16
+ Mixin class for defining Static Timing Analysis (STA) parameters.
17
+ """
15
18
  def __init__(self):
16
19
  super().__init__()
17
20
 
@@ -31,6 +34,67 @@ class OpenROADSTAParameter(OpenROADTask):
31
34
  defvalue="tools/_common/sdc/sc_constraints.sdc",
32
35
  dataroot="siliconcompiler")
33
36
 
37
+ def set_openroad_earlytimingderate(self, derate: float,
38
+ step: Optional[str] = None, index: Optional[str] = None):
39
+ """
40
+ Sets the timing derating factor to use for hold corners.
41
+
42
+ Args:
43
+ derate (float): The derating factor.
44
+ step (str, optional): The specific step to apply this configuration to.
45
+ index (str, optional): The specific index to apply this configuration to.
46
+ """
47
+ self.set("var", "sta_early_timing_derate", derate, step=step, index=index)
48
+
49
+ def set_openroad_latetimingderate(self, derate: float,
50
+ step: Optional[str] = None, index: Optional[str] = None):
51
+ """
52
+ Sets the timing derating factor to use for setup corners.
53
+
54
+ Args:
55
+ derate (float): The derating factor.
56
+ step (str, optional): The specific step to apply this configuration to.
57
+ index (str, optional): The specific index to apply this configuration to.
58
+ """
59
+ self.set("var", "sta_late_timing_derate", derate, step=step, index=index)
60
+
61
+ def set_openroad_topnpaths(self, n: int,
62
+ step: Optional[str] = None, index: Optional[str] = None):
63
+ """
64
+ Sets the number of paths to report timing for.
65
+
66
+ Args:
67
+ n (int): The number of paths.
68
+ step (str, optional): The specific step to apply this configuration to.
69
+ index (str, optional): The specific index to apply this configuration to.
70
+ """
71
+ self.set("var", "sta_top_n_paths", n, step=step, index=index)
72
+
73
+ def set_openroad_definepathgroups(self, enable: bool,
74
+ step: Optional[str] = None, index: Optional[str] = None):
75
+ """
76
+ Enables or disables the generation of path groups for timing reporting.
77
+
78
+ Args:
79
+ enable (bool): True to enable, False to disable.
80
+ step (str, optional): The specific step to apply this configuration to.
81
+ index (str, optional): The specific index to apply this configuration to.
82
+ """
83
+ self.set("var", "sta_define_path_groups", enable, step=step, index=index)
84
+
85
+ def set_openroad_uniquepathgroupsperclock(self, enable: bool,
86
+ step: Optional[str] = None,
87
+ index: Optional[str] = None):
88
+ """
89
+ Enables or disables the generation of separate path groups per clock.
90
+
91
+ Args:
92
+ enable (bool): True to enable, False to disable.
93
+ step (str, optional): The specific step to apply this configuration to.
94
+ index (str, optional): The specific index to apply this configuration to.
95
+ """
96
+ self.set("var", "sta_unique_path_groups_per_clock", enable, step=step, index=index)
97
+
34
98
  def setup(self):
35
99
  super().setup()
36
100
 
@@ -43,6 +107,9 @@ class OpenROADSTAParameter(OpenROADTask):
43
107
 
44
108
 
45
109
  class OpenROADPSMParameter(OpenROADTask):
110
+ """
111
+ Mixin class for defining Power Supply Map (PSM) analysis parameters.
112
+ """
46
113
  def __init__(self):
47
114
  super().__init__()
48
115
 
@@ -50,6 +117,35 @@ class OpenROADPSMParameter(OpenROADTask):
50
117
  "true/false, when true enables IR drop analysis", defvalue=True)
51
118
  self.add_parameter("psm_skip_nets", "[str]", "list of nets to skip power grid analysis on")
52
119
 
120
+ def set_openroad_psmenable(self, enable: bool,
121
+ step: Optional[str] = None, index: Optional[str] = None):
122
+ """
123
+ Enables or disables IR drop analysis.
124
+
125
+ Args:
126
+ enable (bool): True to enable, False to disable.
127
+ step (str, optional): The specific step to apply this configuration to.
128
+ index (str, optional): The specific index to apply this configuration to.
129
+ """
130
+ self.set("var", "psm_enable", enable, step=step, index=index)
131
+
132
+ def add_openroad_psmskipnets(self, nets: Union[str, List[str]],
133
+ step: Optional[str] = None, index: Optional[str] = None,
134
+ clobber: bool = False):
135
+ """
136
+ Adds nets to skip during power grid analysis.
137
+
138
+ Args:
139
+ nets (Union[str, List[str]]): The net(s) to skip.
140
+ step (str, optional): The specific step to apply this configuration to.
141
+ index (str, optional): The specific index to apply this configuration to.
142
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
143
+ """
144
+ if clobber:
145
+ self.set("var", "psm_skip_nets", nets, step=step, index=index)
146
+ else:
147
+ self.add("var", "psm_skip_nets", nets, step=step, index=index)
148
+
53
149
  def setup(self):
54
150
  super().setup()
55
151
 
@@ -59,12 +155,49 @@ class OpenROADPSMParameter(OpenROADTask):
59
155
 
60
156
 
61
157
  class OpenROADPPLLayersParameter(OpenROADTask):
158
+ """
159
+ Mixin class for defining Pin Placement (PPL) layer parameters.
160
+ """
62
161
  def __init__(self):
63
162
  super().__init__()
64
163
 
65
164
  self.add_parameter("pin_layer_horizontal", "[str]", "layers to use for horizontal pins")
66
165
  self.add_parameter("pin_layer_vertical", "[str]", "layers to use for vertical pins")
67
166
 
167
+ def add_openroad_pinlayerhorizontal(self, layers: Union[str, List[str]],
168
+ step: Optional[str] = None, index: Optional[str] = None,
169
+ clobber: bool = False):
170
+ """
171
+ Adds layers to use for horizontal pins.
172
+
173
+ Args:
174
+ layers (Union[str, List[str]]): The layer(s) to add.
175
+ step (str, optional): The specific step to apply this configuration to.
176
+ index (str, optional): The specific index to apply this configuration to.
177
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
178
+ """
179
+ if clobber:
180
+ self.set("var", "pin_layer_horizontal", layers, step=step, index=index)
181
+ else:
182
+ self.add("var", "pin_layer_horizontal", layers, step=step, index=index)
183
+
184
+ def add_openroad_pinlayervertical(self, layers: Union[str, List[str]],
185
+ step: Optional[str] = None, index: Optional[str] = None,
186
+ clobber: bool = False):
187
+ """
188
+ Adds layers to use for vertical pins.
189
+
190
+ Args:
191
+ layers (Union[str, List[str]]): The layer(s) to add.
192
+ step (str, optional): The specific step to apply this configuration to.
193
+ index (str, optional): The specific index to apply this configuration to.
194
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
195
+ """
196
+ if clobber:
197
+ self.set("var", "pin_layer_vertical", layers, step=step, index=index)
198
+ else:
199
+ self.add("var", "pin_layer_vertical", layers, step=step, index=index)
200
+
68
201
  def setup(self):
69
202
  super().setup()
70
203
 
@@ -73,6 +206,9 @@ class OpenROADPPLLayersParameter(OpenROADTask):
73
206
 
74
207
 
75
208
  class OpenROADPPLParameter(OpenROADPPLLayersParameter):
209
+ """
210
+ Mixin class for defining Pin Placement (PPL) parameters.
211
+ """
76
212
  def __init__(self):
77
213
  super().__init__()
78
214
 
@@ -80,6 +216,40 @@ class OpenROADPPLParameter(OpenROADPPLLayersParameter):
80
216
  "additional arguments to pass along to the pin placer.")
81
217
  self.add_parameter("ppl_constraints", "[file]", "pin placement constraints scripts.")
82
218
 
219
+ def add_openroad_pplarguments(self, args: Union[str, List[str]],
220
+ step: Optional[str] = None, index: Optional[str] = None,
221
+ clobber: bool = False):
222
+ """
223
+ Adds additional arguments to pass along to the pin placer.
224
+
225
+ Args:
226
+ args (Union[str, List[str]]): The argument(s) to add.
227
+ step (str, optional): The specific step to apply this configuration to.
228
+ index (str, optional): The specific index to apply this configuration to.
229
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
230
+ """
231
+ if clobber:
232
+ self.set("var", "ppl_arguments", args, step=step, index=index)
233
+ else:
234
+ self.add("var", "ppl_arguments", args, step=step, index=index)
235
+
236
+ def add_openroad_pplconstraints(self, constraints: Union[str, List[str]],
237
+ step: Optional[str] = None, index: Optional[str] = None,
238
+ clobber: bool = False):
239
+ """
240
+ Adds pin placement constraints scripts.
241
+
242
+ Args:
243
+ constraints (Union[str, List[str]]): The constraint file(s) to add.
244
+ step (str, optional): The specific step to apply this configuration to.
245
+ index (str, optional): The specific index to apply this configuration to.
246
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
247
+ """
248
+ if clobber:
249
+ self.set("var", "ppl_constraints", constraints, step=step, index=index)
250
+ else:
251
+ self.add("var", "ppl_constraints", constraints, step=step, index=index)
252
+
83
253
  def setup(self):
84
254
  super().setup()
85
255
 
@@ -91,6 +261,9 @@ class OpenROADPPLParameter(OpenROADPPLLayersParameter):
91
261
 
92
262
 
93
263
  class OpenROADGPLParameter(OpenROADTask):
264
+ """
265
+ Mixin class for defining Global Placement (GPL) parameters.
266
+ """
94
267
  def __init__(self):
95
268
  super().__init__()
96
269
 
@@ -116,6 +289,91 @@ class OpenROADGPLParameter(OpenROADTask):
116
289
  self.add_parameter("pad_global_place", "int",
117
290
  "global placement cell padding in number of sites", defvalue=0)
118
291
 
292
+ def set_openroad_gplskipio(self, enable: bool,
293
+ step: Optional[str] = None, index: Optional[str] = None):
294
+ """
295
+ Enables or disables skipping I/O placement during global placement.
296
+
297
+ Args:
298
+ enable (bool): True to skip I/O placement, False to include it.
299
+ step (str, optional): The specific step to apply this configuration to.
300
+ index (str, optional): The specific index to apply this configuration to.
301
+ """
302
+ self.set("var", "gpl_enable_skip_io", enable, step=step, index=index)
303
+
304
+ def set_openroad_gplskipinitialplace(self, enable: bool,
305
+ step: Optional[str] = None, index: Optional[str] = None):
306
+ """
307
+ Enables or disables skipping initial placement during global placement.
308
+
309
+ Args:
310
+ enable (bool): True to skip initial placement, False to perform it.
311
+ step (str, optional): The specific step to apply this configuration to.
312
+ index (str, optional): The specific index to apply this configuration to.
313
+ """
314
+ self.set("var", "gpl_enable_skip_initial_place", enable, step=step, index=index)
315
+
316
+ def set_openroad_gpluniformplacementadjustment(self, adjustment: float,
317
+ step: Optional[str] = None,
318
+ index: Optional[str] = None):
319
+ """
320
+ Sets the uniform placement adjustment factor.
321
+
322
+ Args:
323
+ adjustment (float): The adjustment factor (0.00 - 0.99).
324
+ step (str, optional): The specific step to apply this configuration to.
325
+ index (str, optional): The specific index to apply this configuration to.
326
+ """
327
+ self.set("var", "gpl_uniform_placement_adjustment", adjustment, step=step, index=index)
328
+
329
+ def set_openroad_gpltimingdriven(self, enable: bool,
330
+ step: Optional[str] = None, index: Optional[str] = None):
331
+ """
332
+ Enables or disables timing-driven global placement.
333
+
334
+ Args:
335
+ enable (bool): True to enable, False to disable.
336
+ step (str, optional): The specific step to apply this configuration to.
337
+ index (str, optional): The specific index to apply this configuration to.
338
+ """
339
+ self.set("var", "gpl_timing_driven", enable, step=step, index=index)
340
+
341
+ def set_openroad_gplroutabilitydriven(self, enable: bool,
342
+ step: Optional[str] = None, index: Optional[str] = None):
343
+ """
344
+ Enables or disables routability-driven global placement.
345
+
346
+ Args:
347
+ enable (bool): True to enable, False to disable.
348
+ step (str, optional): The specific step to apply this configuration to.
349
+ index (str, optional): The specific index to apply this configuration to.
350
+ """
351
+ self.set("var", "gpl_routability_driven", enable, step=step, index=index)
352
+
353
+ def set_openroad_placedensity(self, density: float,
354
+ step: Optional[str] = None, index: Optional[str] = None):
355
+ """
356
+ Sets the global placement density.
357
+
358
+ Args:
359
+ density (float): The target placement density (0.0 - 1.0).
360
+ step (str, optional): The specific step to apply this configuration to.
361
+ index (str, optional): The specific index to apply this configuration to.
362
+ """
363
+ self.set("var", "place_density", density, step=step, index=index)
364
+
365
+ def set_openroad_padglobalplace(self, padding: int,
366
+ step: Optional[str] = None, index: Optional[str] = None):
367
+ """
368
+ Sets the global placement cell padding.
369
+
370
+ Args:
371
+ padding (int): The padding in number of sites.
372
+ step (str, optional): The specific step to apply this configuration to.
373
+ index (str, optional): The specific index to apply this configuration to.
374
+ """
375
+ self.set("var", "pad_global_place", padding, step=step, index=index)
376
+
119
377
  def setup(self):
120
378
  super().setup()
121
379
 
@@ -130,6 +388,9 @@ class OpenROADGPLParameter(OpenROADTask):
130
388
 
131
389
 
132
390
  class OpenROADRSZDRVParameter(OpenROADTask):
391
+ """
392
+ Mixin class for defining Resizer (RSZ) Design Rule Violation (DRV) repair parameters.
393
+ """
133
394
  def __init__(self):
134
395
  super().__init__()
135
396
 
@@ -140,6 +401,30 @@ class OpenROADRSZDRVParameter(OpenROADTask):
140
401
  "specifies the amount of margin to apply to max slew repairs in percent "
141
402
  "(0 - 100)", defvalue=0.0)
142
403
 
404
+ def set_openroad_rszcapmargin(self, margin: float,
405
+ step: Optional[str] = None, index: Optional[str] = None):
406
+ """
407
+ Sets the margin for max capacitance repairs.
408
+
409
+ Args:
410
+ margin (float): The margin in percent (0 - 100).
411
+ step (str, optional): The specific step to apply this configuration to.
412
+ index (str, optional): The specific index to apply this configuration to.
413
+ """
414
+ self.set("var", "rsz_cap_margin", margin, step=step, index=index)
415
+
416
+ def set_openroad_rszslewmargin(self, margin: float,
417
+ step: Optional[str] = None, index: Optional[str] = None):
418
+ """
419
+ Sets the margin for max slew repairs.
420
+
421
+ Args:
422
+ margin (float): The margin in percent (0 - 100).
423
+ step (str, optional): The specific step to apply this configuration to.
424
+ index (str, optional): The specific index to apply this configuration to.
425
+ """
426
+ self.set("var", "rsz_slew_margin", margin, step=step, index=index)
427
+
143
428
  def setup(self):
144
429
  super().setup()
145
430
 
@@ -148,6 +433,9 @@ class OpenROADRSZDRVParameter(OpenROADTask):
148
433
 
149
434
 
150
435
  class OpenROADRSZTimingParameter(OpenROADTask):
436
+ """
437
+ Mixin class for defining Resizer (RSZ) timing repair parameters.
438
+ """
151
439
  def __init__(self):
152
440
  super().__init__()
153
441
 
@@ -169,6 +457,78 @@ class OpenROADRSZTimingParameter(OpenROADTask):
169
457
  "percentage of paths to attempt to recover power (0 - 100)",
170
458
  defvalue=100)
171
459
 
460
+ def set_openroad_rszsetupslackmargin(self, margin: float,
461
+ step: Optional[str] = None, index: Optional[str] = None):
462
+ """
463
+ Sets the margin for setup timing repair.
464
+
465
+ Args:
466
+ margin (float): The margin in ns.
467
+ step (str, optional): The specific step to apply this configuration to.
468
+ index (str, optional): The specific index to apply this configuration to.
469
+ """
470
+ self.set("var", "rsz_setup_slack_margin", margin, step=step, index=index)
471
+
472
+ def set_openroad_rszholdslackmargin(self, margin: float,
473
+ step: Optional[str] = None, index: Optional[str] = None):
474
+ """
475
+ Sets the margin for hold timing repair.
476
+
477
+ Args:
478
+ margin (float): The margin in ns.
479
+ step (str, optional): The specific step to apply this configuration to.
480
+ index (str, optional): The specific index to apply this configuration to.
481
+ """
482
+ self.set("var", "rsz_hold_slack_margin", margin, step=step, index=index)
483
+
484
+ def set_openroad_rszskippinswap(self, skip: bool,
485
+ step: Optional[str] = None, index: Optional[str] = None):
486
+ """
487
+ Enables or disables pin swap optimization.
488
+
489
+ Args:
490
+ skip (bool): True to skip pin swap, False to perform it.
491
+ step (str, optional): The specific step to apply this configuration to.
492
+ index (str, optional): The specific index to apply this configuration to.
493
+ """
494
+ self.set("var", "rsz_skip_pin_swap", skip, step=step, index=index)
495
+
496
+ def set_openroad_rszskipgatecloning(self, skip: bool,
497
+ step: Optional[str] = None, index: Optional[str] = None):
498
+ """
499
+ Enables or disables gate cloning optimization.
500
+
501
+ Args:
502
+ skip (bool): True to skip gate cloning, False to perform it.
503
+ step (str, optional): The specific step to apply this configuration to.
504
+ index (str, optional): The specific index to apply this configuration to.
505
+ """
506
+ self.set("var", "rsz_skip_gate_cloning", skip, step=step, index=index)
507
+
508
+ def set_openroad_rszrepairtns(self, percentage: float,
509
+ step: Optional[str] = None, index: Optional[str] = None):
510
+ """
511
+ Sets the percentage of violating nets to attempt to repair.
512
+
513
+ Args:
514
+ percentage (float): The percentage (0 - 100).
515
+ step (str, optional): The specific step to apply this configuration to.
516
+ index (str, optional): The specific index to apply this configuration to.
517
+ """
518
+ self.set("var", "rsz_repair_tns", percentage, step=step, index=index)
519
+
520
+ def set_openroad_rszrecoverpower(self, percentage: float,
521
+ step: Optional[str] = None, index: Optional[str] = None):
522
+ """
523
+ Sets the percentage of paths to attempt to recover power.
524
+
525
+ Args:
526
+ percentage (float): The percentage (0 - 100).
527
+ step (str, optional): The specific step to apply this configuration to.
528
+ index (str, optional): The specific index to apply this configuration to.
529
+ """
530
+ self.set("var", "rsz_recover_power", percentage, step=step, index=index)
531
+
172
532
  def setup(self):
173
533
  super().setup()
174
534
 
@@ -181,6 +541,9 @@ class OpenROADRSZTimingParameter(OpenROADTask):
181
541
 
182
542
 
183
543
  class OpenROADDPLParameter(OpenROADTask):
544
+ """
545
+ Mixin class for defining Detailed Placement (DPL) parameters.
546
+ """
184
547
  def __init__(self):
185
548
  super().__init__()
186
549
 
@@ -190,6 +553,31 @@ class OpenROADDPLParameter(OpenROADTask):
190
553
  "maximum cell movement in detailed placement in microns, 0 will result "
191
554
  "in the tool default maximum displacement", defvalue=(0, 0))
192
555
 
556
+ def set_openroad_paddetailplace(self, padding: int,
557
+ step: Optional[str] = None, index: Optional[str] = None):
558
+ """
559
+ Sets the detailed placement cell padding.
560
+
561
+ Args:
562
+ padding (int): The padding in number of sites.
563
+ step (str, optional): The specific step to apply this configuration to.
564
+ index (str, optional): The specific index to apply this configuration to.
565
+ """
566
+ self.set("var", "pad_detail_place", padding, step=step, index=index)
567
+
568
+ def set_openroad_dplmaxdisplacement(self, x: float, y: float,
569
+ step: Optional[str] = None, index: Optional[str] = None):
570
+ """
571
+ Sets the maximum cell displacement for detailed placement.
572
+
573
+ Args:
574
+ x (float): The maximum displacement in X (microns).
575
+ y (float): The maximum displacement in Y (microns).
576
+ step (str, optional): The specific step to apply this configuration to.
577
+ index (str, optional): The specific index to apply this configuration to.
578
+ """
579
+ self.set("var", "dpl_max_displacement", (x, y), step=step, index=index)
580
+
193
581
  def setup(self):
194
582
  super().setup()
195
583
 
@@ -198,6 +586,9 @@ class OpenROADDPLParameter(OpenROADTask):
198
586
 
199
587
 
200
588
  class OpenROADFillCellsParameter(OpenROADTask):
589
+ """
590
+ Mixin class for defining filler cell insertion parameters.
591
+ """
201
592
  def __init__(self):
202
593
  super().__init__()
203
594
 
@@ -205,6 +596,18 @@ class OpenROADFillCellsParameter(OpenROADTask):
205
596
  "true/false, use decap fillers along with non-decap fillers",
206
597
  defvalue=True)
207
598
 
599
+ def set_openroad_dplusedecapfillers(self, enable: bool,
600
+ step: Optional[str] = None, index: Optional[str] = None):
601
+ """
602
+ Enables or disables the use of decap fillers.
603
+
604
+ Args:
605
+ enable (bool): True to use decap fillers, False otherwise.
606
+ step (str, optional): The specific step to apply this configuration to.
607
+ index (str, optional): The specific index to apply this configuration to.
608
+ """
609
+ self.set("var", "dpl_use_decap_fillers", enable, step=step, index=index)
610
+
208
611
  def setup(self):
209
612
  super().setup()
210
613
 
@@ -212,6 +615,9 @@ class OpenROADFillCellsParameter(OpenROADTask):
212
615
 
213
616
 
214
617
  class OpenROADDPOParameter(OpenROADTask):
618
+ """
619
+ Mixin class for defining Detailed Placement Optimization (DPO) parameters.
620
+ """
215
621
  def __init__(self):
216
622
  super().__init__()
217
623
 
@@ -223,6 +629,31 @@ class OpenROADDPOParameter(OpenROADTask):
223
629
  "0 will result in the tool default maximum displacement", unit="um",
224
630
  defvalue=(5, 5))
225
631
 
632
+ def set_openroad_dpoenable(self, enable: bool,
633
+ step: Optional[str] = None, index: Optional[str] = None):
634
+ """
635
+ Enables or disables detailed placement optimization.
636
+
637
+ Args:
638
+ enable (bool): True to enable, False to disable.
639
+ step (str, optional): The specific step to apply this configuration to.
640
+ index (str, optional): The specific index to apply this configuration to.
641
+ """
642
+ self.set("var", "dpo_enable", enable, step=step, index=index)
643
+
644
+ def set_openroad_dpomaxdisplacement(self, x: float, y: float,
645
+ step: Optional[str] = None, index: Optional[str] = None):
646
+ """
647
+ Sets the maximum cell displacement for detailed placement optimization.
648
+
649
+ Args:
650
+ x (float): The maximum displacement in X (microns).
651
+ y (float): The maximum displacement in Y (microns).
652
+ step (str, optional): The specific step to apply this configuration to.
653
+ index (str, optional): The specific index to apply this configuration to.
654
+ """
655
+ self.set("var", "dpo_max_displacement", (x, y), step=step, index=index)
656
+
226
657
  def setup(self):
227
658
  super().setup()
228
659
 
@@ -231,6 +662,9 @@ class OpenROADDPOParameter(OpenROADTask):
231
662
 
232
663
 
233
664
  class OpenROADCTSParameter(OpenROADTask):
665
+ """
666
+ Mixin class for defining Clock Tree Synthesis (CTS) parameters.
667
+ """
234
668
  def __init__(self):
235
669
  super().__init__()
236
670
 
@@ -248,6 +682,67 @@ class OpenROADCTSParameter(OpenROADTask):
248
682
  self.add_parameter("cts_obstruction_aware", "bool",
249
683
  "make clock tree synthesis aware of obstructions", defvalue=True)
250
684
 
685
+ def set_openroad_ctsdistancebetweenbuffers(self, distance: float,
686
+ step: Optional[str] = None,
687
+ index: Optional[str] = None):
688
+ """
689
+ Sets the maximum distance between buffers during CTS.
690
+
691
+ Args:
692
+ distance (float): The distance in microns.
693
+ step (str, optional): The specific step to apply this configuration to.
694
+ index (str, optional): The specific index to apply this configuration to.
695
+ """
696
+ self.set("var", "cts_distance_between_buffers", distance, step=step, index=index)
697
+
698
+ def set_openroad_ctsclusterdiameter(self, diameter: float,
699
+ step: Optional[str] = None, index: Optional[str] = None):
700
+ """
701
+ Sets the clustering diameter for CTS.
702
+
703
+ Args:
704
+ diameter (float): The diameter in microns.
705
+ step (str, optional): The specific step to apply this configuration to.
706
+ index (str, optional): The specific index to apply this configuration to.
707
+ """
708
+ self.set("var", "cts_cluster_diameter", diameter, step=step, index=index)
709
+
710
+ def set_openroad_ctsclustersize(self, size: int,
711
+ step: Optional[str] = None, index: Optional[str] = None):
712
+ """
713
+ Sets the cluster size for CTS.
714
+
715
+ Args:
716
+ size (int): The number of instances in a cluster.
717
+ step (str, optional): The specific step to apply this configuration to.
718
+ index (str, optional): The specific index to apply this configuration to.
719
+ """
720
+ self.set("var", "cts_cluster_size", size, step=step, index=index)
721
+
722
+ def set_openroad_ctsbalancelevels(self, enable: bool,
723
+ step: Optional[str] = None, index: Optional[str] = None):
724
+ """
725
+ Enables or disables level balancing during CTS.
726
+
727
+ Args:
728
+ enable (bool): True to enable, False to disable.
729
+ step (str, optional): The specific step to apply this configuration to.
730
+ index (str, optional): The specific index to apply this configuration to.
731
+ """
732
+ self.set("var", "cts_balance_levels", enable, step=step, index=index)
733
+
734
+ def set_openroad_ctsobstructionaware(self, enable: bool,
735
+ step: Optional[str] = None, index: Optional[str] = None):
736
+ """
737
+ Enables or disables obstruction-aware CTS.
738
+
739
+ Args:
740
+ enable (bool): True to enable, False to disable.
741
+ step (str, optional): The specific step to apply this configuration to.
742
+ index (str, optional): The specific index to apply this configuration to.
743
+ """
744
+ self.set("var", "cts_obstruction_aware", enable, step=step, index=index)
745
+
251
746
  def setup(self):
252
747
  super().setup()
253
748
 
@@ -259,6 +754,9 @@ class OpenROADCTSParameter(OpenROADTask):
259
754
 
260
755
 
261
756
  class OpenROADGRTGeneralParameter(OpenROADTask):
757
+ """
758
+ Mixin class for defining general Global Routing (GRT) parameters.
759
+ """
262
760
  def __init__(self):
263
761
  super().__init__()
264
762
 
@@ -274,6 +772,66 @@ class OpenROADGRTGeneralParameter(OpenROADTask):
274
772
  self.add_parameter("grt_clock_max_layer", "str",
275
773
  "maximum layer to use for global routing of clock nets")
276
774
 
775
+ def set_openroad_grtmacroextension(self, extension: int,
776
+ step: Optional[str] = None, index: Optional[str] = None):
777
+ """
778
+ Sets the macro extension distance for global routing.
779
+
780
+ Args:
781
+ extension (int): The extension distance in number of gcells.
782
+ step (str, optional): The specific step to apply this configuration to.
783
+ index (str, optional): The specific index to apply this configuration to.
784
+ """
785
+ self.set("var", "grt_macro_extension", extension, step=step, index=index)
786
+
787
+ def set_openroad_grtsignalminlayer(self, layer: str,
788
+ step: Optional[str] = None, index: Optional[str] = None):
789
+ """
790
+ Sets the minimum layer for signal routing.
791
+
792
+ Args:
793
+ layer (str): The layer name.
794
+ step (str, optional): The specific step to apply this configuration to.
795
+ index (str, optional): The specific index to apply this configuration to.
796
+ """
797
+ self.set("var", "grt_signal_min_layer", layer, step=step, index=index)
798
+
799
+ def set_openroad_grtsignalmaxlayer(self, layer: str,
800
+ step: Optional[str] = None, index: Optional[str] = None):
801
+ """
802
+ Sets the maximum layer for signal routing.
803
+
804
+ Args:
805
+ layer (str): The layer name.
806
+ step (str, optional): The specific step to apply this configuration to.
807
+ index (str, optional): The specific index to apply this configuration to.
808
+ """
809
+ self.set("var", "grt_signal_max_layer", layer, step=step, index=index)
810
+
811
+ def set_openroad_grtclockminlayer(self, layer: str,
812
+ step: Optional[str] = None, index: Optional[str] = None):
813
+ """
814
+ Sets the minimum layer for clock routing.
815
+
816
+ Args:
817
+ layer (str): The layer name.
818
+ step (str, optional): The specific step to apply this configuration to.
819
+ index (str, optional): The specific index to apply this configuration to.
820
+ """
821
+ self.set("var", "grt_clock_min_layer", layer, step=step, index=index)
822
+
823
+ def set_openroad_grtclockmaxlayer(self, layer: str,
824
+ step: Optional[str] = None, index: Optional[str] = None):
825
+ """
826
+ Sets the maximum layer for clock routing.
827
+
828
+ Args:
829
+ layer (str): The layer name.
830
+ step (str, optional): The specific step to apply this configuration to.
831
+ index (str, optional): The specific index to apply this configuration to.
832
+ """
833
+ self.set("var", "grt_clock_max_layer", layer, step=step, index=index)
834
+
277
835
  def setup(self):
278
836
  super().setup()
279
837
 
@@ -298,6 +856,9 @@ class OpenROADGRTGeneralParameter(OpenROADTask):
298
856
 
299
857
 
300
858
  class OpenROADGRTParameter(OpenROADGRTGeneralParameter):
859
+ """
860
+ Mixin class for defining Global Routing (GRT) parameters.
861
+ """
301
862
  def __init__(self):
302
863
  super().__init__()
303
864
 
@@ -308,6 +869,30 @@ class OpenROADGRTParameter(OpenROADGRTGeneralParameter):
308
869
  "maximum number of iterations to use in global routing when attempting "
309
870
  "to solve overflow", defvalue=100)
310
871
 
872
+ def set_openroad_grtallowcongestion(self, allow: bool,
873
+ step: Optional[str] = None, index: Optional[str] = None):
874
+ """
875
+ Enables or disables allowing congestion in global routing.
876
+
877
+ Args:
878
+ allow (bool): True to allow congestion, False otherwise.
879
+ step (str, optional): The specific step to apply this configuration to.
880
+ index (str, optional): The specific index to apply this configuration to.
881
+ """
882
+ self.set("var", "grt_allow_congestion", allow, step=step, index=index)
883
+
884
+ def set_openroad_grtoverflowiter(self, iterations: int,
885
+ step: Optional[str] = None, index: Optional[str] = None):
886
+ """
887
+ Sets the maximum number of overflow iterations for global routing.
888
+
889
+ Args:
890
+ iterations (int): The number of iterations.
891
+ step (str, optional): The specific step to apply this configuration to.
892
+ index (str, optional): The specific index to apply this configuration to.
893
+ """
894
+ self.set("var", "grt_overflow_iter", iterations, step=step, index=index)
895
+
311
896
  def setup(self):
312
897
  super().setup()
313
898
 
@@ -316,6 +901,9 @@ class OpenROADGRTParameter(OpenROADGRTGeneralParameter):
316
901
 
317
902
 
318
903
  class OpenROADANTParameter(OpenROADTask):
904
+ """
905
+ Mixin class for defining Antenna repair parameters.
906
+ """
319
907
  def __init__(self):
320
908
  super().__init__()
321
909
 
@@ -325,6 +913,30 @@ class OpenROADANTParameter(OpenROADTask):
325
913
  self.add_parameter("ant_margin", "float", "adds a margin to the antenna ratios (0 - 100)",
326
914
  defvalue=0)
327
915
 
916
+ def set_openroad_antiterations(self, iterations: int,
917
+ step: Optional[str] = None, index: Optional[str] = None):
918
+ """
919
+ Sets the maximum number of antenna repair iterations.
920
+
921
+ Args:
922
+ iterations (int): The number of iterations.
923
+ step (str, optional): The specific step to apply this configuration to.
924
+ index (str, optional): The specific index to apply this configuration to.
925
+ """
926
+ self.set("var", "ant_iterations", iterations, step=step, index=index)
927
+
928
+ def set_openroad_antmargin(self, margin: float,
929
+ step: Optional[str] = None, index: Optional[str] = None):
930
+ """
931
+ Sets the margin for antenna ratios.
932
+
933
+ Args:
934
+ margin (float): The margin (0 - 100).
935
+ step (str, optional): The specific step to apply this configuration to.
936
+ index (str, optional): The specific index to apply this configuration to.
937
+ """
938
+ self.set("var", "ant_margin", margin, step=step, index=index)
939
+
328
940
  def setup(self):
329
941
  super().setup()
330
942
 
@@ -333,6 +945,9 @@ class OpenROADANTParameter(OpenROADTask):
333
945
 
334
946
 
335
947
  class _OpenROADDRTCommonParameter(OpenROADTask):
948
+ """
949
+ Base mixin class for defining common Detailed Routing (DRT) parameters.
950
+ """
336
951
  def __init__(self):
337
952
  super().__init__()
338
953
 
@@ -345,6 +960,54 @@ class _OpenROADDRTCommonParameter(OpenROADTask):
345
960
  "list of layers to treat as unidirectional regardless of what the tech "
346
961
  "lef specifies")
347
962
 
963
+ def set_openroad_drtprocessnode(self, node: str,
964
+ step: Optional[str] = None, index: Optional[str] = None):
965
+ """
966
+ Sets the process node for detailed routing.
967
+
968
+ Args:
969
+ node (str): The process node name.
970
+ step (str, optional): The specific step to apply this configuration to.
971
+ index (str, optional): The specific index to apply this configuration to.
972
+ """
973
+ self.set("var", "drt_process_node", node, step=step, index=index)
974
+
975
+ def add_openroad_detailedroutedefaultvia(self, vias: Union[str, List[str]],
976
+ step: Optional[str] = None,
977
+ index: Optional[str] = None,
978
+ clobber: bool = False):
979
+ """
980
+ Adds default vias to use for detailed routing.
981
+
982
+ Args:
983
+ vias (Union[str, List[str]]): The via(s) to add.
984
+ step (str, optional): The specific step to apply this configuration to.
985
+ index (str, optional): The specific index to apply this configuration to.
986
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
987
+ """
988
+ if clobber:
989
+ self.set("var", "detailed_route_default_via", vias, step=step, index=index)
990
+ else:
991
+ self.add("var", "detailed_route_default_via", vias, step=step, index=index)
992
+
993
+ def add_openroad_detailedrouteunidirectionallayer(self, layers: Union[str, List[str]],
994
+ step: Optional[str] = None,
995
+ index: Optional[str] = None,
996
+ clobber: bool = False):
997
+ """
998
+ Adds layers to treat as unidirectional during detailed routing.
999
+
1000
+ Args:
1001
+ layers (Union[str, List[str]]): The layer(s) to add.
1002
+ step (str, optional): The specific step to apply this configuration to.
1003
+ index (str, optional): The specific index to apply this configuration to.
1004
+ clobber (bool, optional): If True, overwrites the existing list. Defaults to False.
1005
+ """
1006
+ if clobber:
1007
+ self.set("var", "detailed_route_unidirectional_layer", layers, step=step, index=index)
1008
+ else:
1009
+ self.add("var", "detailed_route_unidirectional_layer", layers, step=step, index=index)
1010
+
348
1011
  def setup(self):
349
1012
  super().setup()
350
1013
 
@@ -363,29 +1026,112 @@ class _OpenROADDRTCommonParameter(OpenROADTask):
363
1026
 
364
1027
 
365
1028
  class OpenROADDRTPinAccessParameter(_OpenROADDRTCommonParameter):
1029
+ """
1030
+ Mixin class for defining Detailed Routing (DRT) pin access parameters.
1031
+ """
366
1032
  def __init__(self):
367
1033
  super().__init__()
368
1034
 
369
1035
 
370
1036
  class OpenROADDRTParameter(_OpenROADDRTCommonParameter):
1037
+ """
1038
+ Mixin class for defining Detailed Routing (DRT) parameters.
1039
+ """
371
1040
  def __init__(self):
372
1041
  super().__init__()
373
1042
 
374
1043
  self.add_parameter("drt_disable_via_gen", "bool",
375
1044
  "true/false, when true turns off via generation in detailed router "
376
1045
  "and only uses the specified tech vias", defvalue=False)
377
- self.add_parameter("drt_via_in_pin_bottom_layer", "str", "TODO")
378
- self.add_parameter("drt_via_in_pin_top_layer", "str", "TODO")
379
- self.add_parameter("drt_repair_pdn_vias", "str", "TODO")
1046
+ self.add_parameter("drt_via_in_pin_bottom_layer", "str",
1047
+ "bottom layer to allow vias inside pins")
1048
+ self.add_parameter("drt_via_in_pin_top_layer", "str",
1049
+ "top layer to allow vias inside pins")
1050
+ self.add_parameter("drt_repair_pdn_vias", "str",
1051
+ "layer to repair PDN vias on")
380
1052
 
381
1053
  self.add_parameter("drt_report_interval", "int",
382
1054
  "reporting interval in steps for generating a DRC report.", defvalue=5)
383
1055
  self.add_parameter("drt_end_iteration", "int",
384
1056
  "end iteration for detailed routing")
385
1057
 
1058
+ def set_openroad_drtdisableviagen(self, disable: bool,
1059
+ step: Optional[str] = None, index: Optional[str] = None):
1060
+ """
1061
+ Enables or disables automatic via generation in the detailed router.
1062
+
1063
+ Args:
1064
+ disable (bool): True to disable via generation, False to enable.
1065
+ step (str, optional): The specific step to apply this configuration to.
1066
+ index (str, optional): The specific index to apply this configuration to.
1067
+ """
1068
+ self.set("var", "drt_disable_via_gen", disable, step=step, index=index)
1069
+
1070
+ def set_openroad_drtviainpinbottomlayer(self, layer: str,
1071
+ step: Optional[str] = None,
1072
+ index: Optional[str] = None):
1073
+ """
1074
+ Sets the bottom layer to allow vias inside pins.
1075
+
1076
+ Args:
1077
+ layer (str): The layer name.
1078
+ step (str, optional): The specific step to apply this configuration to.
1079
+ index (str, optional): The specific index to apply this configuration to.
1080
+ """
1081
+ self.set("var", "drt_via_in_pin_bottom_layer", layer, step=step, index=index)
1082
+
1083
+ def set_openroad_drtviainpintoplayer(self, layer: str,
1084
+ step: Optional[str] = None, index: Optional[str] = None):
1085
+ """
1086
+ Sets the top layer to allow vias inside pins.
1087
+
1088
+ Args:
1089
+ layer (str): The layer name.
1090
+ step (str, optional): The specific step to apply this configuration to.
1091
+ index (str, optional): The specific index to apply this configuration to.
1092
+ """
1093
+ self.set("var", "drt_via_in_pin_top_layer", layer, step=step, index=index)
1094
+
1095
+ def set_openroad_drtrepairpdnvias(self, layer: str,
1096
+ step: Optional[str] = None, index: Optional[str] = None):
1097
+ """
1098
+ Sets the layer to repair PDN vias on.
1099
+
1100
+ Args:
1101
+ layer (str): The layer name.
1102
+ step (str, optional): The specific step to apply this configuration to.
1103
+ index (str, optional): The specific index to apply this configuration to.
1104
+ """
1105
+ self.set("var", "drt_repair_pdn_vias", layer, step=step, index=index)
1106
+
1107
+ def set_openroad_drtreportinterval(self, interval: int,
1108
+ step: Optional[str] = None, index: Optional[str] = None):
1109
+ """
1110
+ Sets the reporting interval for detailed routing.
1111
+
1112
+ Args:
1113
+ interval (int): The interval in steps.
1114
+ step (str, optional): The specific step to apply this configuration to.
1115
+ index (str, optional): The specific index to apply this configuration to.
1116
+ """
1117
+ self.set("var", "drt_report_interval", interval, step=step, index=index)
1118
+
1119
+ def set_openroad_drtenditeration(self, iteration: int,
1120
+ step: Optional[str] = None, index: Optional[str] = None):
1121
+ """
1122
+ Sets the end iteration for detailed routing.
1123
+
1124
+ Args:
1125
+ iteration (int): The iteration number.
1126
+ step (str, optional): The specific step to apply this configuration to.
1127
+ index (str, optional): The specific index to apply this configuration to.
1128
+ """
1129
+ self.set("var", "drt_end_iteration", iteration, step=step, index=index)
1130
+
386
1131
  def setup(self):
387
1132
  super().setup()
388
1133
 
1134
+ self.add_required_key("var", "drt_disable_via_gen")
389
1135
  if not self.get("var", "drt_disable_via_gen"):
390
1136
  if self.pdk.get("tool", "openroad", "drt_disable_via_gen"):
391
1137
  self.add_required_key(self.pdk, "tool", "openroad", "drt_disable_via_gen")
@@ -398,7 +1144,17 @@ class OpenROADDRTParameter(_OpenROADDRTCommonParameter):
398
1144
  self.set("var", "drt_repair_pdn_vias",
399
1145
  self.pdk.get("tool", "openroad", "drt_repair_pdn_vias"))
400
1146
 
401
- self.add_required_key("var", "drt_disable_via_gen")
1147
+ bottom_via_layer = self.get("var", "drt_via_in_pin_bottom_layer")
1148
+ top_via_layer = self.get("var", "drt_via_in_pin_top_layer")
1149
+ if not bottom_via_layer or not top_via_layer:
1150
+ pdk_via_layers = self.pdk.get("tool", "openroad", "drt_via_in_pin_layers")
1151
+ if pdk_via_layers:
1152
+ self.add_required_key(self.pdk, "tool", "openroad", "drt_via_in_pin_layers")
1153
+ if not bottom_via_layer:
1154
+ self.set("var", "drt_via_in_pin_bottom_layer", pdk_via_layers[0])
1155
+ if not top_via_layer:
1156
+ self.set("var", "drt_via_in_pin_top_layer", pdk_via_layers[1])
1157
+
402
1158
  if self.get("var", "drt_via_in_pin_bottom_layer"):
403
1159
  self.add_required_key("var", "drt_via_in_pin_bottom_layer")
404
1160
  if self.get("var", "drt_via_in_pin_top_layer"):
@@ -635,13 +1391,22 @@ class APRTask(OpenROADTask):
635
1391
  def _add_pnr_outputs(self):
636
1392
  self.add_output_file(ext="sdc")
637
1393
  self.add_output_file(ext="vg")
1394
+ self.add_output_file(ext="lec.vg")
638
1395
  self.add_output_file(ext="def")
639
1396
  self.add_output_file(ext="odb")
640
1397
 
1398
+ for lib in self.project.get("asic", "asiclib"):
1399
+ libobj = self.project.get("library", lib, field="schema")
1400
+ for celltype in ["decap", "tie", "filler", "tap", "endcap", "antenna", "physicalonly"]:
1401
+ if libobj.valid("asic", "cells", celltype) and \
1402
+ libobj.get("asic", "cells", celltype):
1403
+ self.add_required_key(libobj, "asic", "cells", celltype)
1404
+
641
1405
  def _get_pex_mapping(self):
642
1406
  corners = {}
643
- for constraint in self.project.getkeys('constraint', 'timing'):
644
- pexcorner = self.project.get('constraint', 'timing', constraint, 'pexcorner',
1407
+ for constraint in self.project.getkeys('constraint', 'timing', 'scenario'):
1408
+ pexcorner = self.project.get('constraint', 'timing', 'scenario',
1409
+ constraint, 'pexcorner',
645
1410
  step=self.step, index=self.index)
646
1411
  if pexcorner:
647
1412
  corners[constraint] = pexcorner
@@ -649,13 +1414,17 @@ class APRTask(OpenROADTask):
649
1414
  return corners
650
1415
 
651
1416
  def _get_constraint_by_check(self, check: str) -> str:
652
- for constraint in self.project.getkeys('constraint', 'timing'):
653
- if check in self.project.get('constraint', 'timing', constraint, 'check',
1417
+ for constraint in self.project.getkeys('constraint', 'timing', 'scenario'):
1418
+ if check in self.project.get('constraint', 'timing', 'scenario',
1419
+ constraint, 'check',
654
1420
  step=self.step, index=self.index):
655
1421
  return constraint
656
1422
 
657
1423
  # if not specified, just pick the first constraint available
658
- return self.project.getkeys('constraint', 'timing')[0]
1424
+ scenarios = self.project.getkeys('constraint', 'timing', 'scenario')
1425
+ if not scenarios:
1426
+ raise ValueError("No timing scenarios defined in project constraints.")
1427
+ return scenarios[0]
659
1428
 
660
1429
  def _build_pex_estimation_file(self):
661
1430
  corners = self._get_pex_mapping()
@@ -761,9 +1530,9 @@ class APRTask(OpenROADTask):
761
1530
  ],
762
1531
  "peakpower": [
763
1532
  *[f"power/{corner}.rpt"
764
- for corner in self.project.getkeys('constraint', 'timing')],
1533
+ for corner in self.project.getkeys('constraint', 'timing', 'scenario')],
765
1534
  *[f"images/heatmap/power_density/{corner}.png"
766
- for corner in self.project.getkeys('constraint', 'timing')]
1535
+ for corner in self.project.getkeys('constraint', 'timing', 'scenario')]
767
1536
  ],
768
1537
  "drvs": [
769
1538
  "timing/drv_violators.rpt",