librelane 2.4.0.dev8__py3-none-any.whl → 3.0.0.dev22__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.

Potentially problematic release.


This version of librelane might be problematic. Click here for more details.

Files changed (62) hide show
  1. librelane/__main__.py +12 -15
  2. librelane/common/__init__.py +1 -1
  3. librelane/common/drc.py +88 -7
  4. librelane/common/misc.py +6 -6
  5. librelane/common/toolbox.py +1 -1
  6. librelane/config/config.py +5 -1
  7. librelane/config/flow.py +51 -66
  8. librelane/config/pdk_compat.py +79 -2
  9. librelane/config/preprocessor.py +1 -1
  10. librelane/config/variable.py +2 -2
  11. librelane/flows/classic.py +1 -0
  12. librelane/flows/flow.py +3 -6
  13. librelane/flows/sequential.py +85 -40
  14. librelane/plugins.py +1 -1
  15. librelane/scripts/magic/common/read.tcl +2 -2
  16. librelane/scripts/magic/gds/extras_mag.tcl +2 -2
  17. librelane/scripts/odbpy/diodes.py +2 -2
  18. librelane/scripts/openroad/common/dpl.tcl +1 -1
  19. librelane/scripts/openroad/common/grt.tcl +3 -3
  20. librelane/scripts/openroad/common/io.tcl +163 -45
  21. librelane/scripts/openroad/common/resizer.tcl +1 -40
  22. librelane/scripts/openroad/common/set_global_connections.tcl +2 -2
  23. librelane/scripts/openroad/common/set_power_nets.tcl +1 -1
  24. librelane/scripts/openroad/common/set_rc.tcl +159 -40
  25. librelane/scripts/openroad/cts.tcl +37 -6
  26. librelane/scripts/openroad/cut_rows.tcl +19 -4
  27. librelane/scripts/openroad/drt.tcl +59 -8
  28. librelane/scripts/openroad/dump_rc.tcl +105 -0
  29. librelane/scripts/openroad/fill.tcl +2 -2
  30. librelane/scripts/openroad/floorplan.tcl +5 -3
  31. librelane/scripts/openroad/gpl.tcl +7 -8
  32. librelane/scripts/openroad/insert_buffer.tcl +2 -2
  33. librelane/scripts/openroad/ioplacer.tcl +1 -2
  34. librelane/scripts/openroad/irdrop.tcl +3 -3
  35. librelane/scripts/openroad/pdn.tcl +17 -18
  36. librelane/scripts/openroad/rcx.tcl +1 -1
  37. librelane/scripts/openroad/repair_design.tcl +14 -7
  38. librelane/scripts/openroad/repair_design_postgrt.tcl +13 -6
  39. librelane/scripts/openroad/rsz_timing_postcts.tcl +13 -12
  40. librelane/scripts/openroad/rsz_timing_postgrt.tcl +13 -12
  41. librelane/scripts/openroad/sta/check_macro_instances.tcl +1 -1
  42. librelane/scripts/openroad/tapcell.tcl +13 -6
  43. librelane/scripts/openroad/ungpl.tcl +23 -0
  44. librelane/state/__init__.py +1 -1
  45. librelane/state/design_format.py +194 -142
  46. librelane/state/state.py +20 -21
  47. librelane/steps/checker.py +12 -1
  48. librelane/steps/common_variables.py +4 -4
  49. librelane/steps/cvc_rv.py +1 -1
  50. librelane/steps/klayout.py +14 -6
  51. librelane/steps/magic.py +18 -2
  52. librelane/steps/misc.py +1 -1
  53. librelane/steps/odb.py +50 -31
  54. librelane/steps/openroad.py +455 -128
  55. librelane/steps/pyosys.py +20 -5
  56. librelane/steps/step.py +17 -20
  57. librelane/steps/tclstep.py +9 -7
  58. librelane/steps/yosys.py +1 -1
  59. {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/METADATA +1 -1
  60. {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/RECORD +62 -60
  61. {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/WHEEL +0 -0
  62. {librelane-2.4.0.dev8.dist-info → librelane-3.0.0.dev22.dist-info}/entry_points.txt +0 -0
@@ -26,6 +26,7 @@ from typing import (
26
26
  Union,
27
27
  )
28
28
 
29
+ from deprecated.sphinx import deprecated
29
30
  from rapidfuzz import process, fuzz, utils
30
31
 
31
32
  from .flow import Flow, FlowException, FlowError
@@ -40,6 +41,10 @@ from ..steps import (
40
41
  )
41
42
 
42
43
  Substitution = Union[str, Type[Step], None]
44
+ SubstitutionsObject = Union[
45
+ Dict[str, Substitution],
46
+ List[Tuple[str, Substitution]],
47
+ ]
43
48
 
44
49
 
45
50
  class SequentialFlow(Flow):
@@ -69,20 +74,53 @@ class SequentialFlow(Flow):
69
74
  :cvar gating_config_vars: A mapping from step ID (wildcards) to lists of
70
75
  Boolean variable names. All Boolean variables must be True for a step with
71
76
  a specific ID to execute.
77
+
78
+ :cvar Substitutions: Consumed by the subclass initializer - allows for a
79
+ quick interface where steps can be removed, replaced, appended or
80
+ prepended. After subclass intialization, it is set to ``None``, and
81
+ a new subclass must be created to modify substitutions further.
82
+
83
+ The list of substitutions may be specified as either a dictionary
84
+ or a list of tuples: while the former is more terse, the latter is
85
+ allows using the same key more than once.
86
+
87
+ The substitutions are mappings from Step IDs or objects to Step IDs,
88
+ objects, or ``None``. In case of ``None``, the step in question is
89
+ removed.
90
+
91
+ In case the key is specified as a string, you may add ``-`` as a prefix
92
+ to the Step ID to indicate you want to insert a step before the step
93
+ in question, and similary ``+`` indicates you want to insert a step
94
+ after the step in question. You may not prepend or append ``None``.
95
+
96
+ Step IDs are made unique after every substitution, i.e., whenever the
97
+ substitution occurs, the first instance of a Step in a sequential flow
98
+ shall have its ID unadulterated, while the next instance will have
99
+ ``-1``, the one after ``-2``, etc. If ``-1`` is removed, the previous
100
+ ``-2`` shall become ``-1``, for example.
72
101
  """
73
102
 
74
- Substitutions: Optional[Dict[str, Union[str, Type[Step], None]]] = None
103
+ Substitutions: Optional[SubstitutionsObject] = None
75
104
  gating_config_vars: Dict[str, List[str]] = {}
76
105
 
106
+ def __init__(
107
+ self,
108
+ *args,
109
+ **kwargs,
110
+ ):
111
+ self.Steps = self.Steps.copy() # Break global reference
112
+ super().__init__(*args, **kwargs)
113
+
114
+ # ---
115
+
77
116
  def __init_subclass__(Self, scm_type=None, name=None, **kwargs):
78
117
  Self.Steps = Self.Steps.copy() # Break global reference
79
118
  Self.config_vars = Self.config_vars.copy()
80
119
  Self.gating_config_vars = Self.gating_config_vars.copy()
81
- if substitute := Self.Substitutions:
82
- for key, item in substitute.items():
83
- Self.__substitute_step(Self, key, item)
84
-
85
120
  Self.__normalize_step_ids(Self)
121
+ if Self.Substitutions:
122
+ Self.__substitute_in_place(Self, Self.Substitutions)
123
+ Self.Substitutions = None
86
124
 
87
125
  # Validate Gating Config Vars
88
126
  variables_by_name = {}
@@ -108,7 +146,7 @@ class SequentialFlow(Flow):
108
146
  )
109
147
 
110
148
  @classmethod
111
- def make(Self, step_ids: List[str]) -> Type[SequentialFlow]:
149
+ def Make(Self, step_ids: List[str]) -> Type[SequentialFlow]:
112
150
  Step_list = []
113
151
  for name in step_ids:
114
152
  step = Step.factory.get(name)
@@ -123,9 +161,16 @@ class SequentialFlow(Flow):
123
161
  return CustomSequentialFlow
124
162
 
125
163
  @classmethod
126
- def Substitute(
127
- Self, Substitutions: Dict[str, Substitution]
128
- ) -> Type[SequentialFlow]:
164
+ @deprecated(
165
+ "use .Make",
166
+ version="3.0.0",
167
+ action="once",
168
+ )
169
+ def make(Self, step_ids: List[str]) -> Type[SequentialFlow]:
170
+ return Self.Make(step_ids)
171
+
172
+ @classmethod
173
+ def Substitute(Self, Substitutions: SubstitutionsObject) -> Type[SequentialFlow]:
129
174
  """
130
175
  Convenience method to quickly subclass a sequential flow and add
131
176
  Substitutions to it.
@@ -136,20 +181,19 @@ class SequentialFlow(Flow):
136
181
  """
137
182
  return type(Self.__name__ + "'", (Self,), {"Substitutions": Substitutions})
138
183
 
139
- def __init__(
140
- self,
141
- *args,
142
- Substitute: Optional[Dict[str, Union[str, Type[Step], None]]] = None,
143
- **kwargs,
184
+ @staticmethod
185
+ def __substitute_in_place(
186
+ target: Type[SequentialFlow],
187
+ Substitutions: Optional[SubstitutionsObject],
144
188
  ):
145
- self.Steps = self.Steps.copy() # Break global reference
146
-
147
- if substitute := Substitute:
148
- for key, item in substitute.items():
149
- self.__substitute_step(self, key, item)
150
- self.__normalize_step_ids(self)
151
-
152
- super().__init__(*args, **kwargs)
189
+ if Substitutions is None:
190
+ return Substitutions
191
+ if isinstance(Substitutions, dict):
192
+ for key, item in Substitutions.items():
193
+ target.__substitute_step(target, key, item)
194
+ else:
195
+ for key, item in Substitutions:
196
+ target.__substitute_step(target, key, item)
153
197
 
154
198
  @staticmethod
155
199
  def __substitute_step(
@@ -189,23 +233,23 @@ class SequentialFlow(Flow):
189
233
  if with_step is None:
190
234
  for index in reversed(step_indices):
191
235
  del target.Steps[index]
192
- return
193
-
194
- if isinstance(with_step, str):
195
- with_step_opt = Step.factory.get(with_step)
196
- if with_step_opt is None:
197
- raise FlowException(
198
- f"Could not {mode} '{id}' with '{with_step}': no replacement step with ID '{with_step}' found."
199
- )
200
- with_step = with_step_opt
236
+ else:
237
+ if isinstance(with_step, str):
238
+ with_step_opt = Step.factory.get(with_step)
239
+ if with_step_opt is None:
240
+ raise FlowException(
241
+ f"Could not {mode} '{id}' with '{with_step}': no replacement step with ID '{with_step}' found."
242
+ )
243
+ with_step = with_step_opt
201
244
 
202
- for i in step_indices:
203
- if mode == "replace":
204
- target.Steps[i] = with_step
205
- elif mode == "append":
206
- target.Steps.insert(i + 1, with_step)
207
- elif mode == "prepend":
208
- target.Steps.insert(i, with_step)
245
+ for i in step_indices:
246
+ if mode == "replace":
247
+ target.Steps[i] = with_step
248
+ elif mode == "append":
249
+ target.Steps.insert(i + 1, with_step)
250
+ elif mode == "prepend":
251
+ target.Steps.insert(i, with_step)
252
+ target.__normalize_step_ids(target)
209
253
 
210
254
  @staticmethod
211
255
  def __normalize_step_ids(target: Union[SequentialFlow, Type[SequentialFlow]]):
@@ -213,14 +257,15 @@ class SequentialFlow(Flow):
213
257
 
214
258
  for i, step in enumerate(target.Steps):
215
259
  counter = 0
216
- id = step.id
260
+ imp_id = step.get_implementation_id()
261
+ id = imp_id
217
262
  if (
218
263
  id == NotImplemented
219
264
  ): # Will be validated later by initialization: ignore for now
220
265
  continue
221
266
  while id in ids_used:
222
267
  counter += 1
223
- id = f"{step.id}-{counter}"
268
+ id = f"{imp_id}-{counter}"
224
269
  if id != step.id:
225
270
  target.Steps[i] = step.with_id(id)
226
271
  ids_used.add(id)
librelane/plugins.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Efabless Corporation
1
+ # Copyright 2024 Efabless Corporation
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -55,8 +55,8 @@ proc read_extra_gds {} {
55
55
  set old_readonly [gds readonly]
56
56
  gds rescale false
57
57
  gds readonly true
58
- if { [info exist ::env(EXTRA_GDS_FILES)] } {
59
- set gds_files_in $::env(EXTRA_GDS_FILES)
58
+ if { [info exist ::env(EXTRA_GDS)] } {
59
+ set gds_files_in $::env(EXTRA_GDS)
60
60
  foreach gds_file $gds_files_in {
61
61
  puts "> gds read $gds_file"
62
62
  gds read $gds_file
@@ -25,8 +25,8 @@ if { $::env(MAGIC_GDS_POLYGON_SUBCELLS) } {
25
25
  gds polygon subcells true
26
26
  }
27
27
 
28
- if { [info exist ::env(EXTRA_GDS_FILES)] } {
29
- set gds_files_in $::env(EXTRA_GDS_FILES)
28
+ if { [info exist ::env(EXTRA_GDS)] } {
29
+ set gds_files_in $::env(EXTRA_GDS)
30
30
  foreach gds_file $gds_files_in {
31
31
  gds read $gds_file
32
32
 
@@ -330,8 +330,8 @@ class DiodeInserter:
330
330
  "--threshold",
331
331
  "threshold_microns",
332
332
  type=Decimal,
333
- default=None,
334
- help="Minimum Manhattan distance of a net to be considered an antenna risk requiring a diode. By default, the value used is 200 * the minimum site width.",
333
+ required=True,
334
+ help="Minimum Manhattan distance of a net to be considered an antenna risk requiring a diode.",
335
335
  )
336
336
  @click_odb
337
337
  def place(
@@ -15,7 +15,7 @@ source $::env(SCRIPTS_DIR)/openroad/common/dpl_cell_pad.tcl
15
15
 
16
16
  remove_fillers
17
17
 
18
- detailed_placement\
18
+ log_cmd detailed_placement\
19
19
  -max_displacement [subst { $::env(PL_MAX_DISPLACEMENT_X) $::env(PL_MAX_DISPLACEMENT_Y) }]
20
20
 
21
21
  if { [info exists ::env(PL_OPTIMIZE_MIRRORING)] && $::env(PL_OPTIMIZE_MIRRORING) } {
@@ -26,7 +26,7 @@ lappend arg_list -verbose
26
26
  if { $::env(GRT_ALLOW_CONGESTION) == 1 } {
27
27
  lappend arg_list -allow_congestion
28
28
  }
29
- puts $arg_list
30
- global_route {*}$arg_list
31
29
 
32
- write_guide $::env(STEP_DIR)/after_grt.guide
30
+ log_cmd global_route {*}$arg_list
31
+
32
+ write_guide $::env(STEP_DIR)/after_grt.guide
@@ -1,4 +1,4 @@
1
- # Copyright 2022-2024 Efabless Corporation
1
+ # Copyright 2022-2025 Efabless Corporation
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -125,14 +125,14 @@ proc read_current_netlist {args} {
125
125
  flags {-powered}
126
126
 
127
127
  if { [info exists flags(-powered)] } {
128
- puts "Reading top-level powered netlist at '$::env(CURRENT_POWERED_NETLIST)'…"
129
- if {[catch {read_verilog $::env(CURRENT_POWERED_NETLIST)} errmsg]} {
128
+ puts "Reading top-level powered netlist at '$::env(CURRENT_PNL)'…"
129
+ if {[catch {read_verilog $::env(CURRENT_PNL)} errmsg]} {
130
130
  puts stderr $errmsg
131
131
  exit 1
132
132
  }
133
133
  } else {
134
- puts "Reading top-level netlist at '$::env(CURRENT_NETLIST)'…"
135
- if {[catch {read_verilog $::env(CURRENT_NETLIST)} errmsg]} {
134
+ puts "Reading top-level netlist at '$::env(CURRENT_NL)'…"
135
+ if {[catch {read_verilog $::env(CURRENT_NL)} errmsg]} {
136
136
  puts stderr $errmsg
137
137
  exit 1
138
138
  }
@@ -153,7 +153,7 @@ proc read_timing_info {args} {
153
153
  return
154
154
  }
155
155
  set corner_name $::env(_CURRENT_CORNER_NAME)
156
- define_corners $corner_name
156
+ log_cm define_corners $corner_name
157
157
 
158
158
  puts "Reading timing models for corner $corner_name…"
159
159
 
@@ -240,31 +240,35 @@ proc read_spefs {} {
240
240
  }
241
241
 
242
242
  proc read_pnr_libs {args} {
243
- # _PNR_LIBS contains all libs and extra libs but with known-bad cells
244
- # excluded, so OpenROAD can use cells by functionality and come up
245
- # with a valid design.
246
-
247
- # If there are ANY libs already read- just leave
248
- if { [get_libs -quiet *] != {} } {
249
- return
250
- }
251
-
252
- define_corners $::env(DEFAULT_CORNER)
253
-
254
- foreach lib $::env(_PNR_LIBS) {
255
- puts "Reading library file at '$lib'…"
256
- read_liberty $lib
257
- }
258
- if { [info exists ::env(_MACRO_LIBS) ] } {
259
- foreach macro_lib $::env(_MACRO_LIBS) {
260
- puts "Reading macro library file at '$macro_lib'…"
261
- read_liberty $macro_lib
243
+ set i "0"
244
+ set tc_key "_LIB_CORNER_$i"
245
+ set corner_names [list]
246
+ while { [info exists ::env($tc_key)] } {
247
+ set corner_name [lindex $::env($tc_key) 0]
248
+ set corner_libs [lreplace $::env($tc_key) 0 0]
249
+ set corner($corner_name) $corner_libs
250
+ incr i
251
+ set tc_key "_LIB_CORNER_$i"
252
+ lappend corner_names $corner_name
253
+ }
254
+
255
+ define_corners {*}[array name corner]
256
+
257
+ foreach corner_name [array name corner] {
258
+ puts "Reading timing models for corner $corner_name…"
259
+
260
+ set corner_models $corner($corner_name)
261
+ foreach model $corner_models {
262
+ puts "Reading timing library for the '$corner_name' corner at '$model'…"
263
+ read_liberty -corner $corner_name $model
262
264
  }
263
- }
264
- if { [info exists ::env(EXTRA_LIBS) ] } {
265
- foreach extra_lib $::env(EXTRA_LIBS) {
266
- puts "Reading extra library file at '$extra_lib'…"
267
- read_liberty $extra_lib
265
+
266
+ if { [info exists ::env(EXTRA_LIBS) ] } {
267
+ puts "Reading explicitly-specified extra libs for $corner_name…"
268
+ foreach extra_lib $::env(EXTRA_LIBS) {
269
+ puts "Reading extra timing library for the '$corner_name' corner at '$extra_lib'…"
270
+ read_liberty -corner $corner_name $extra_lib
271
+ }
268
272
  }
269
273
  }
270
274
  }
@@ -302,6 +306,7 @@ proc read_current_odb {args} {
302
306
  keys {}\
303
307
  flags {}
304
308
 
309
+ read_pnr_libs
305
310
  puts "Reading OpenROAD database at '$::env(CURRENT_ODB)'…"
306
311
  if { [ catch {read_db $::env(CURRENT_ODB)} errmsg ]} {
307
312
  puts stderr $errmsg
@@ -311,7 +316,6 @@ proc read_current_odb {args} {
311
316
  set_global_vars
312
317
 
313
318
  # Read supporting views (if applicable)
314
- read_pnr_libs
315
319
  read_current_sdc
316
320
  set_dont_use_cells
317
321
  }
@@ -402,32 +406,32 @@ proc write_views {args} {
402
406
  write_db $::env(SAVE_ODB)
403
407
  }
404
408
 
405
- if { [info exists ::env(SAVE_NETLIST)] } {
406
- puts "Writing netlist to '$::env(SAVE_NETLIST)'…"
407
- write_verilog $::env(SAVE_NETLIST)
409
+ if { [info exists ::env(SAVE_NL)] } {
410
+ puts "Writing netlist to '$::env(SAVE_NL)'…"
411
+ write_verilog $::env(SAVE_NL)
408
412
  }
409
413
 
410
- if { [info exists ::env(SAVE_POWERED_NETLIST)] } {
411
- puts "Writing powered netlist to '$::env(SAVE_POWERED_NETLIST)'…"
412
- write_verilog -include_pwr_gnd $::env(SAVE_POWERED_NETLIST)
414
+ if { [info exists ::env(SAVE_PNL)] } {
415
+ puts "Writing powered netlist to '$::env(SAVE_PNL)'…"
416
+ write_verilog -include_pwr_gnd $::env(SAVE_PNL)
413
417
  }
414
418
 
415
- if { [info exists ::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)] } {
419
+ if { [info exists ::env(SAVE_SDF_PNL)] } {
416
420
  set exclude_cells "[get_timing_excluded_cells]"
417
- puts "Writing nofill powered netlist to '$::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)'…"
421
+ puts "Writing nofill powered netlist to '$::env(SAVE_SDF_PNL)'…"
418
422
  puts "Excluding $exclude_cells"
419
423
  write_verilog -include_pwr_gnd \
420
- -remove_cells "$exclude_cells"\
421
- $::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)
424
+ -remove_cells "[get_timing_excluded_cells]"\
425
+ $::env(SAVE_SDF_PNL)
422
426
  }
423
427
 
424
- if { [info exists ::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)] } {
428
+ if { [info exists ::env(SAVE_LOGICAL_PNL)] } {
425
429
  set exclude_cells "[get_physical_cells]"
426
- puts "Writing nofilldiode powered netlist to '$::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)'…"
430
+ puts "Writing nofilldiode powered netlist to '$::env(SAVE_LOGICAL_PNL)'…"
427
431
  puts "Excluding $exclude_cells"
428
432
  write_verilog -include_pwr_gnd \
429
- -remove_cells "$exclude_cells"\
430
- $::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)
433
+ -remove_cells "[get_physical_cells]"\
434
+ $::env(SAVE_LOGICAL_PNL)
431
435
  }
432
436
 
433
437
  if { [info exists ::env(SAVE_OPENROAD_LEF)] } {
@@ -538,3 +542,117 @@ if { [namespace exists utl] } {
538
542
  puts "%OL_METRIC $metric $value"
539
543
  }
540
544
  }
545
+
546
+ proc exit_unless_gui {{status 0}} {
547
+ if { ![info exists ::env(_OPENROAD_GUI)] || !$::env(_OPENROAD_GUI) } {
548
+ exit $status
549
+ }
550
+ }
551
+
552
+ proc find_unfixed_macros {} {
553
+ set macros [list]
554
+
555
+ foreach inst [$::block getInsts] {
556
+ set inst_master [$inst getMaster]
557
+
558
+ # BLOCK means MACRO cells
559
+ if { ![string match [$inst_master getType] "BLOCK"] } {
560
+ continue
561
+ }
562
+
563
+ if { [$inst isFixed] } {
564
+ continue
565
+ }
566
+
567
+ lappend macros $inst
568
+ }
569
+ return $macros
570
+ }
571
+
572
+ proc get_layers {args} {
573
+ sta::parse_key_args "get_layers" args \
574
+ keys {-types -map}\
575
+ flags {-constrained}
576
+
577
+ if { ![info exists keys(-types)] } {
578
+ puts "\[ERROR\] Invalid usage of get_layers: -types is required."
579
+ }
580
+
581
+ set layers [$::tech getLayers]
582
+ set result [list]
583
+ set adding [expr ![info exists flags(-constrained)]]
584
+ foreach layer $layers {
585
+ set name [$layer getName]
586
+ if {"$::env(RT_MIN_LAYER)" == "$name"} {
587
+ set adding 1
588
+ }
589
+ if { [lsearch $keys(-types) [$layer getType]] != -1 && $adding} {
590
+ lappend result $layer
591
+ }
592
+
593
+ if {"$::env(RT_MAX_LAYER)" == "$name"} {
594
+ set adding [info exists flags(-constrained)]
595
+ }
596
+
597
+ }
598
+ if { [info exists keys(-map)] } {
599
+ set result [lmap layer $result "\$layer $keys(-map)"]
600
+ }
601
+ return $result
602
+ }
603
+
604
+ proc append_if_exists_argument {list_arg glob_variable_name option} {
605
+ upvar $list_arg local_array
606
+ if [info exists ::env($glob_variable_name) ] {
607
+ lappend local_array $option $::env($glob_variable_name)
608
+ }
609
+ }
610
+
611
+ proc append_if_flag {list_arg glob_variable_name flag} {
612
+ upvar $list_arg local_array
613
+ if { [info exists ::env($glob_variable_name)] && $::env($glob_variable_name) } {
614
+ lappend local_array $flag
615
+ }
616
+ }
617
+ proc append_if_not_flag {list_arg glob_variable_name flag} {
618
+ upvar $list_arg local_array
619
+ if { [info exists ::env($glob_variable_name)] && !$::env($glob_variable_name) } {
620
+ lappend local_array $flag
621
+ }
622
+ }
623
+
624
+ # Code below adapted from OpenROAD Flow Scripts under the following license:
625
+ #
626
+ # BSD 3-Clause License
627
+ #
628
+ # Copyright (c) 2018-2023, The Regents of the University of California
629
+ # All rights reserved.
630
+ #
631
+ # Redistribution and use in source and binary forms, with or without
632
+ # modification, are permitted provided that the following conditions are met:
633
+
634
+ # * Redistributions of source code must retain the above copyright notice, this
635
+ # list of conditions and the following disclaimer.
636
+ #
637
+ # * Redistributions in binary form must reproduce the above copyright notice,
638
+ # this list of conditions and the following disclaimer in the documentation
639
+ # and/or other materials provided with the distribution.
640
+ #
641
+ # * Neither the name of the copyright holder nor the names of its
642
+ # contributors may be used to endorse or promote products derived from
643
+ # this software without specific prior written permission.
644
+ #
645
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
646
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
647
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
648
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
649
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
650
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
651
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
652
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
653
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
654
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
655
+ proc log_cmd {cmd args} {
656
+ puts "+ $cmd [join $args " "]"
657
+ return [$cmd {*}$args]
658
+ }
@@ -1,4 +1,4 @@
1
- # Copyright 2022-2023 Efabless Corporation
1
+ # Copyright 2022-2024 Efabless Corporation
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -11,45 +11,6 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- proc load_rsz_corners {args} {
15
- set i "0"
16
- set tc_key "RSZ_CORNER_$i"
17
- while { [info exists ::env($tc_key)] } {
18
- set corner_name [lindex $::env($tc_key) 0]
19
- set corner_libs [lreplace $::env($tc_key) 0 0]
20
-
21
- set corner($corner_name) $corner_libs
22
-
23
- incr i
24
- set tc_key "RSZ_CORNER_$i"
25
- }
26
-
27
- if { $i == "0" } {
28
- puts stderr "\[WARNING\] No resizer-specific timing information read."
29
- return
30
- }
31
-
32
- define_corners {*}[array name corner]
33
-
34
- foreach corner_name [array name corner] {
35
- puts "Reading timing models for corner $corner_name…"
36
-
37
- set corner_models $corner($corner_name)
38
- foreach model $corner_models {
39
- puts "Reading timing library for the '$corner_name' corner at '$model'…"
40
- read_liberty -corner $corner_name $model
41
- }
42
-
43
- if { [info exists ::env(EXTRA_LIBS) ] } {
44
- puts "Reading explicitly-specified extra libs for $corner_name…"
45
- foreach extra_lib $::env(EXTRA_LIBS) {
46
- puts "Reading extra timing library for the '$corner_name' corner at '$extra_lib'…"
47
- read_liberty -corner $corner_name $extra_lib
48
- }
49
- }
50
- }
51
- }
52
-
53
14
  proc set_dont_touch_objects {args} {
54
15
  set rx $::env(RSZ_DONT_TOUCH_RX)
55
16
  if { $rx != {^$} } {
@@ -45,7 +45,7 @@ proc set_global_connections {} {
45
45
 
46
46
  if { $power_pin == "" || $ground_pin == "" } {
47
47
  puts "PDN_MACRO_CONNECTIONS missing power and ground pin names"
48
- exit -1
48
+ exit_unless_gui 1
49
49
  }
50
50
 
51
51
  set matched 0
@@ -57,7 +57,7 @@ proc set_global_connections {} {
57
57
  }
58
58
  if { $matched != 1 } {
59
59
  puts "\[ERROR\] No match found for regular expression '$instance_name' defined in PDN_MACRO_CONNECTIONS."
60
- exit 1
60
+ exit_unless_gui 1
61
61
  }
62
62
 
63
63
  add_global_connection \
@@ -17,7 +17,7 @@ if { [info exists ::env(VDD_NETS)] || [info exists ::env(GND_NETS)] } {
17
17
  # current assumption: they cannot have a common ground
18
18
  if { ! [info exists ::env(VDD_NETS)] || ! [info exists ::env(GND_NETS)] } {
19
19
  puts stderr "\[ERROR\] VDD_NETS and GND_NETS must *both* either be defined or undefined"
20
- exit -1
20
+ exit_unless_gui 1
21
21
  }
22
22
  set ::env(VDD_NET) [lindex $::env(VDD_NETS) 0]
23
23
  set ::env(GND_NET) [lindex $::env(GND_NETS) 0]