librelane 2.4.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.

Potentially problematic release.


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

Files changed (170) hide show
  1. librelane/__init__.py +38 -0
  2. librelane/__main__.py +479 -0
  3. librelane/__version__.py +43 -0
  4. librelane/common/__init__.py +63 -0
  5. librelane/common/cli.py +75 -0
  6. librelane/common/drc.py +246 -0
  7. librelane/common/generic_dict.py +319 -0
  8. librelane/common/metrics/__init__.py +35 -0
  9. librelane/common/metrics/__main__.py +413 -0
  10. librelane/common/metrics/library.py +354 -0
  11. librelane/common/metrics/metric.py +186 -0
  12. librelane/common/metrics/util.py +279 -0
  13. librelane/common/misc.py +456 -0
  14. librelane/common/ring_buffer.py +63 -0
  15. librelane/common/tcl.py +80 -0
  16. librelane/common/toolbox.py +549 -0
  17. librelane/common/tpe.py +41 -0
  18. librelane/common/types.py +116 -0
  19. librelane/config/__init__.py +32 -0
  20. librelane/config/__main__.py +155 -0
  21. librelane/config/config.py +1025 -0
  22. librelane/config/flow.py +490 -0
  23. librelane/config/pdk_compat.py +255 -0
  24. librelane/config/preprocessor.py +464 -0
  25. librelane/config/removals.py +45 -0
  26. librelane/config/variable.py +743 -0
  27. librelane/container.py +285 -0
  28. librelane/env_info.py +320 -0
  29. librelane/examples/spm/config.yaml +33 -0
  30. librelane/examples/spm/pin_order.cfg +14 -0
  31. librelane/examples/spm/src/impl.sdc +73 -0
  32. librelane/examples/spm/src/signoff.sdc +68 -0
  33. librelane/examples/spm/src/spm.v +73 -0
  34. librelane/examples/spm/verify/spm_tb.v +106 -0
  35. librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
  36. librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
  37. librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
  38. librelane/examples/spm-user_project_wrapper/config.json +13 -0
  39. librelane/examples/spm-user_project_wrapper/defines.v +66 -0
  40. librelane/examples/spm-user_project_wrapper/template.def +7656 -0
  41. librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
  42. librelane/flows/__init__.py +24 -0
  43. librelane/flows/builtins.py +18 -0
  44. librelane/flows/classic.py +327 -0
  45. librelane/flows/cli.py +463 -0
  46. librelane/flows/flow.py +1049 -0
  47. librelane/flows/misc.py +71 -0
  48. librelane/flows/optimizing.py +179 -0
  49. librelane/flows/sequential.py +367 -0
  50. librelane/flows/synth_explore.py +173 -0
  51. librelane/help/__main__.py +39 -0
  52. librelane/logging/__init__.py +40 -0
  53. librelane/logging/logger.py +323 -0
  54. librelane/open_pdks_rev +1 -0
  55. librelane/plugins.py +21 -0
  56. librelane/py.typed +0 -0
  57. librelane/scripts/base.sdc +80 -0
  58. librelane/scripts/klayout/Readme.md +2 -0
  59. librelane/scripts/klayout/open_design.py +63 -0
  60. librelane/scripts/klayout/render.py +121 -0
  61. librelane/scripts/klayout/stream_out.py +176 -0
  62. librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
  63. librelane/scripts/klayout/xor.drc +120 -0
  64. librelane/scripts/magic/Readme.md +1 -0
  65. librelane/scripts/magic/common/read.tcl +114 -0
  66. librelane/scripts/magic/def/antenna_check.tcl +35 -0
  67. librelane/scripts/magic/def/mag.tcl +19 -0
  68. librelane/scripts/magic/def/mag_gds.tcl +79 -0
  69. librelane/scripts/magic/drc.tcl +78 -0
  70. librelane/scripts/magic/extract_spice.tcl +98 -0
  71. librelane/scripts/magic/gds/drc_batch.tcl +74 -0
  72. librelane/scripts/magic/gds/erase_box.tcl +32 -0
  73. librelane/scripts/magic/gds/extras_mag.tcl +45 -0
  74. librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
  75. librelane/scripts/magic/get_bbox.tcl +11 -0
  76. librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
  77. librelane/scripts/magic/lef/maglef.tcl +26 -0
  78. librelane/scripts/magic/lef.tcl +57 -0
  79. librelane/scripts/magic/open.tcl +28 -0
  80. librelane/scripts/magic/wrapper.tcl +21 -0
  81. librelane/scripts/netgen/setup.tcl +28 -0
  82. librelane/scripts/odbpy/apply_def_template.py +49 -0
  83. librelane/scripts/odbpy/cell_frequency.py +107 -0
  84. librelane/scripts/odbpy/check_antenna_properties.py +116 -0
  85. librelane/scripts/odbpy/contextualize.py +109 -0
  86. librelane/scripts/odbpy/defutil.py +573 -0
  87. librelane/scripts/odbpy/diodes.py +373 -0
  88. librelane/scripts/odbpy/disconnected_pins.py +305 -0
  89. librelane/scripts/odbpy/eco_buffer.py +181 -0
  90. librelane/scripts/odbpy/eco_diode.py +139 -0
  91. librelane/scripts/odbpy/filter_unannotated.py +100 -0
  92. librelane/scripts/odbpy/io_place.py +482 -0
  93. librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
  94. librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
  95. librelane/scripts/odbpy/label_macro_pins.py +277 -0
  96. librelane/scripts/odbpy/lefutil.py +97 -0
  97. librelane/scripts/odbpy/placers.py +162 -0
  98. librelane/scripts/odbpy/power_utils.py +397 -0
  99. librelane/scripts/odbpy/random_place.py +57 -0
  100. librelane/scripts/odbpy/reader.py +250 -0
  101. librelane/scripts/odbpy/remove_buffers.py +173 -0
  102. librelane/scripts/odbpy/snap_to_grid.py +57 -0
  103. librelane/scripts/odbpy/wire_lengths.py +93 -0
  104. librelane/scripts/openroad/antenna_check.tcl +20 -0
  105. librelane/scripts/openroad/antenna_repair.tcl +31 -0
  106. librelane/scripts/openroad/basic_mp.tcl +24 -0
  107. librelane/scripts/openroad/buffer_list.tcl +10 -0
  108. librelane/scripts/openroad/common/dpl.tcl +24 -0
  109. librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
  110. librelane/scripts/openroad/common/grt.tcl +32 -0
  111. librelane/scripts/openroad/common/io.tcl +540 -0
  112. librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
  113. librelane/scripts/openroad/common/resizer.tcl +103 -0
  114. librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
  115. librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
  116. librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
  117. librelane/scripts/openroad/common/set_rc.tcl +75 -0
  118. librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
  119. librelane/scripts/openroad/cts.tcl +80 -0
  120. librelane/scripts/openroad/cut_rows.tcl +24 -0
  121. librelane/scripts/openroad/dpl.tcl +24 -0
  122. librelane/scripts/openroad/drt.tcl +37 -0
  123. librelane/scripts/openroad/fill.tcl +30 -0
  124. librelane/scripts/openroad/floorplan.tcl +145 -0
  125. librelane/scripts/openroad/gpl.tcl +88 -0
  126. librelane/scripts/openroad/grt.tcl +30 -0
  127. librelane/scripts/openroad/gui.tcl +37 -0
  128. librelane/scripts/openroad/insert_buffer.tcl +127 -0
  129. librelane/scripts/openroad/ioplacer.tcl +67 -0
  130. librelane/scripts/openroad/irdrop.tcl +51 -0
  131. librelane/scripts/openroad/pdn.tcl +52 -0
  132. librelane/scripts/openroad/rcx.tcl +32 -0
  133. librelane/scripts/openroad/repair_design.tcl +70 -0
  134. librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
  135. librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
  136. librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
  137. librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
  138. librelane/scripts/openroad/sta/corner.tcl +393 -0
  139. librelane/scripts/openroad/tapcell.tcl +25 -0
  140. librelane/scripts/openroad/write_views.tcl +27 -0
  141. librelane/scripts/pyosys/construct_abc_script.py +177 -0
  142. librelane/scripts/pyosys/json_header.py +84 -0
  143. librelane/scripts/pyosys/synthesize.py +493 -0
  144. librelane/scripts/pyosys/ys_common.py +153 -0
  145. librelane/scripts/tclsh/hello.tcl +1 -0
  146. librelane/state/__init__.py +24 -0
  147. librelane/state/__main__.py +61 -0
  148. librelane/state/design_format.py +195 -0
  149. librelane/state/state.py +359 -0
  150. librelane/steps/__init__.py +61 -0
  151. librelane/steps/__main__.py +510 -0
  152. librelane/steps/checker.py +637 -0
  153. librelane/steps/common_variables.py +340 -0
  154. librelane/steps/cvc_rv.py +169 -0
  155. librelane/steps/klayout.py +509 -0
  156. librelane/steps/magic.py +576 -0
  157. librelane/steps/misc.py +160 -0
  158. librelane/steps/netgen.py +253 -0
  159. librelane/steps/odb.py +1088 -0
  160. librelane/steps/openroad.py +2460 -0
  161. librelane/steps/openroad_alerts.py +102 -0
  162. librelane/steps/pyosys.py +640 -0
  163. librelane/steps/step.py +1571 -0
  164. librelane/steps/tclstep.py +288 -0
  165. librelane/steps/verilator.py +222 -0
  166. librelane/steps/yosys.py +371 -0
  167. librelane-2.4.0.dist-info/METADATA +169 -0
  168. librelane-2.4.0.dist-info/RECORD +170 -0
  169. librelane-2.4.0.dist-info/WHEEL +4 -0
  170. librelane-2.4.0.dist-info/entry_points.txt +9 -0
librelane/flows/cli.py ADDED
@@ -0,0 +1,463 @@
1
+ # Copyright 2023 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import os
15
+ from functools import partial, wraps
16
+ from concurrent.futures import ThreadPoolExecutor
17
+ from typing import Optional, Union
18
+
19
+ from click import (
20
+ Context,
21
+ Parameter,
22
+ echo,
23
+ )
24
+ from cloup import (
25
+ option,
26
+ argument,
27
+ option_group,
28
+ Choice,
29
+ Path,
30
+ )
31
+ from cloup.constraints import (
32
+ mutually_exclusive,
33
+ )
34
+ from cloup.typing import Decorator
35
+
36
+ from .flow import Flow
37
+ from ..common import set_tpe, cli, get_opdks_rev, _get_process_limit
38
+ from ..logging import set_log_level, verbose, err, options, LogLevels
39
+ from ..state import State, InvalidState
40
+
41
+
42
+ def set_log_level_cb(
43
+ ctx: Context,
44
+ param: Parameter,
45
+ value: Optional[str],
46
+ ):
47
+ if value is None:
48
+ return
49
+
50
+ level: Union[str, int] = value
51
+ try:
52
+ try:
53
+ level = int(value)
54
+ except ValueError:
55
+ pass
56
+ set_log_level(level)
57
+ except ValueError as e:
58
+ err(f"Invalid logging level {value}: {e}.")
59
+ echo(ctx.get_help())
60
+ ctx.exit(-1)
61
+
62
+
63
+ def set_worker_count_cb(
64
+ ctx: Context,
65
+ param: Parameter,
66
+ value: Optional[int],
67
+ ):
68
+ if value is None:
69
+ return None
70
+
71
+ set_tpe(ThreadPoolExecutor(max_workers=value))
72
+
73
+
74
+ def initial_state_cb(
75
+ ctx: Context,
76
+ param: Parameter,
77
+ value: Optional[str],
78
+ ):
79
+ if value is None:
80
+ return None
81
+
82
+ try:
83
+ initial_state_str = open(value, encoding="utf8").read()
84
+ except Exception as e:
85
+ err(f"Failed to read initial state: {e}")
86
+ ctx.exit(-1)
87
+ try:
88
+ initial_state = State.loads(initial_state_str, validate_path=True)
89
+ except InvalidState as e:
90
+ err(e)
91
+ ctx.exit(-1)
92
+
93
+ return initial_state
94
+
95
+
96
+ def only_cb(
97
+ ctx: Context,
98
+ param: Parameter,
99
+ value: Optional[str],
100
+ ):
101
+ if value is not None:
102
+ ctx.obj = ctx.obj or {}
103
+ ctx.obj["only"] = value
104
+ return value
105
+
106
+
107
+ def from_to_cb(
108
+ ctx: Context,
109
+ param: Parameter,
110
+ value: Optional[str],
111
+ ):
112
+ if isinstance(ctx.obj, dict) and ctx.obj.get("only"):
113
+ return ctx.obj.get("only")
114
+ return value
115
+
116
+
117
+ def condensed_cb(ctx: Context, param: Parameter, value: bool):
118
+ if value:
119
+ options.set_condensed_mode(True)
120
+ options.set_show_progress_bar(False)
121
+
122
+
123
+ def progressbar_cb(ctx: Context, param: Parameter, value: Optional[bool]):
124
+ if value is not None:
125
+ options.set_show_progress_bar(value)
126
+
127
+
128
+ def cloup_flow_opts(
129
+ *,
130
+ config_options: bool = True,
131
+ run_options: bool = True,
132
+ sequential_flow_controls: bool = True,
133
+ sequential_flow_reproducible: bool = False,
134
+ pdk_options: bool = True,
135
+ log_level: bool = True,
136
+ jobs: bool = True,
137
+ accept_config_files: bool = True,
138
+ volare_by_default: bool = True,
139
+ volare_pdk_override: Optional[str] = None,
140
+ _enable_debug_flags: bool = False,
141
+ enable_overwrite_flag: bool = False,
142
+ enable_initial_state_element: bool = False,
143
+ ) -> Decorator:
144
+ """
145
+ Creates a wrapper that appends a number of LibreLane flow-related flags to a
146
+ function decorated with @cloup.command (https://cloup.readthedocs.io/en/stable/autoapi/cloup/index.html#cloup.command).
147
+
148
+ The following keyword arguments will be passed to the decorated function.
149
+ * Those postfixed ‡ are compatible with the constructor for :class:`Flow`.
150
+ * Those postfixed § are compatible with the :meth:`Flow.start`.
151
+
152
+ * Flow configuration options (if parameter ``config_options`` is ``True``):
153
+ * ``flow_name``: ``Optional[str]``: A valid flow ID to be used with :meth:`Flow.factory.get`
154
+ * ``config_override_strings``‡: ``Optional[Iterable[str]]``
155
+ * Sequential flow controls (if parameter ``sequential_flow_controls`` is ``True``)
156
+ * ``frm``§: ``Optional[str]``: Start from a step with this ID. Supported by sequential flows.
157
+ * ``to``§: ``Optional[str]``: Stop at a step with this id. Supported by sequential flows.
158
+ * ``skip``§: ``Iterable[str]``: Skip these steps. Supported by sequential flows.
159
+ * Sequential flow reproducible (if parameter ``sequential_flow_reproducible`` is ``True``)
160
+ * ``reproducible``§: ``str``: Create a reproducible for a step with is ID, aborting the flow afterwards. Supported by sequential flows.
161
+ * Flow run options (if parameter ``run_options`` is ``True``):
162
+ * ``tag``§: ``Optional[str]``
163
+ * ``last_run``§: ``bool``: If ``True``, ``tag`` is guaranteed to be None.
164
+ * ``with_initial_state``§: ``Optional[State]``
165
+ * PDK options
166
+ * ``use_volare``: ``bool``
167
+ * ``pdk_root``‡: ``Optional[str]``
168
+ * ``pdk``‡: ``str``
169
+ * ``scl``‡: ``Optional[str]``
170
+ * ``config_files``: ``Iterable[str]``: Paths to configuration files (if
171
+ parameter ``accept_config_files`` is ``True``)
172
+
173
+ :param config_options: Enables flow configuration and starting CLI flags
174
+ :param sequential_flow_controls: Enables flow control CLI flags
175
+ :param flow_run_options: Enables tag CLI flags
176
+ :param pdk_options: Enables PDK CLI flags
177
+ :param log_level: Enables ``--log-level`` CLI flag
178
+ :param jobs: Enables ``-j/--jobs`` CLI flag
179
+ :param accept_config_files: Accepts configuration file paths as CLI arguments
180
+ :param volare_by_default: If ``pdk_options`` is ``True``, this changes whether
181
+ Ciel is used by default for this CLI or not.
182
+ :returns: The wrapper
183
+ """
184
+ o = partial(option, show_default=True)
185
+
186
+ def decorate(f):
187
+ if config_options:
188
+ f = option_group(
189
+ "Flow configuration options",
190
+ o(
191
+ "-f",
192
+ "--flow",
193
+ "flow_name",
194
+ type=Choice(Flow.factory.list(), case_sensitive=False),
195
+ default=None,
196
+ help="The built-in LibreLane flow to use for this run",
197
+ ),
198
+ o(
199
+ "-c",
200
+ "--override-config",
201
+ "config_override_strings",
202
+ type=str,
203
+ multiple=True,
204
+ help="For this run only- override a configuration variable with a certain value. In the format KEY=VALUE. Can be specified multiple times. Values must be valid JSON values, and keys must not use their deprecated names.",
205
+ ),
206
+ )(f)
207
+ if run_options:
208
+ f = o(
209
+ "-i",
210
+ "--with-initial-state",
211
+ type=Path(
212
+ exists=True,
213
+ file_okay=True,
214
+ dir_okay=False,
215
+ ),
216
+ default=None,
217
+ callback=initial_state_cb,
218
+ help="Use this JSON file as an initial state. If this is not specified, the latest `state_out.json` of the run directory will be used. If none exist, an empty initial state is created.",
219
+ )(f)
220
+ f = o(
221
+ "--design-dir",
222
+ "design_dir",
223
+ type=Path(
224
+ exists=True,
225
+ file_okay=False,
226
+ dir_okay=True,
227
+ ),
228
+ default=None,
229
+ help="The top-level directory for your design that configuration objects may resolve paths relative to.",
230
+ )(f)
231
+ if enable_overwrite_flag:
232
+ f = o(
233
+ "--overwrite",
234
+ is_flag=True,
235
+ default=False,
236
+ help="Overwrite run, if exists.",
237
+ )(f)
238
+ if _enable_debug_flags:
239
+ f = option_group(
240
+ "Debug flags",
241
+ o(
242
+ "--force-run-dir",
243
+ "_force_run_dir",
244
+ type=Path(
245
+ exists=True,
246
+ file_okay=False,
247
+ dir_okay=True,
248
+ ),
249
+ hidden=True,
250
+ default=None,
251
+ ),
252
+ )(f)
253
+ f = option_group(
254
+ "Run options",
255
+ o(
256
+ "--run-tag",
257
+ "tag",
258
+ default=None,
259
+ type=str,
260
+ help="An optional name to use for this particular run of an LibreLane-based flow. Used to create the run directory.",
261
+ ),
262
+ o(
263
+ "--last-run",
264
+ is_flag=True,
265
+ default=False,
266
+ help="Use the last run as the run tag.",
267
+ ),
268
+ constraint=mutually_exclusive,
269
+ )(f)
270
+ if sequential_flow_controls:
271
+ f = option_group(
272
+ "Sequential flow controls",
273
+ o(
274
+ "-F",
275
+ "--from",
276
+ "frm",
277
+ type=str,
278
+ default=None,
279
+ callback=from_to_cb,
280
+ help="Start from a step with this id. Supported by sequential flows.",
281
+ ),
282
+ o(
283
+ "-T",
284
+ "--to",
285
+ type=str,
286
+ default=None,
287
+ callback=from_to_cb,
288
+ help="Stop at a step with this id. Supported by sequential flows.",
289
+ ),
290
+ o(
291
+ "--only",
292
+ type=str,
293
+ default=None,
294
+ expose_value=False,
295
+ is_eager=True,
296
+ callback=only_cb,
297
+ help="Shorthand to set both --from and --to to the same value. Overrides the values from both.",
298
+ ),
299
+ o(
300
+ "-S",
301
+ "--skip",
302
+ type=str,
303
+ multiple=True,
304
+ help="Skip these steps. Supported by sequential flows.",
305
+ ),
306
+ )(f)
307
+ if sequential_flow_reproducible:
308
+ f = o(
309
+ "--reproducible",
310
+ type=str,
311
+ help="Create a reproducible for the step matching this ID, then abort the flow. Supported by sequential flows.",
312
+ )(f)
313
+ if log_level:
314
+ f = o(
315
+ "--log-level",
316
+ type=cli.IntEnumChoice(LogLevels),
317
+ default=None,
318
+ help="A logging level. Set to VERBOSE or higher to silence subprocess logs. [default: unchanged from SUBPROCESS]",
319
+ callback=set_log_level_cb,
320
+ expose_value=False,
321
+ show_default=False,
322
+ )(f)
323
+ f = o(
324
+ "--show-progress-bar/--hide-progress-bar",
325
+ type=bool,
326
+ help="Whether to show the progress bar when running Flows. [default: show]",
327
+ default=None,
328
+ callback=progressbar_cb,
329
+ expose_value=False,
330
+ )(f)
331
+ f = o(
332
+ "--condensed/--full",
333
+ type=bool,
334
+ help="In condensed mode, subprocess logs are suppressed regardless of step, --hide-progress-bar is the default, and the log messages themselves are a bit more terse. Useful for debugging.",
335
+ default=False,
336
+ is_eager=True,
337
+ callback=condensed_cb,
338
+ expose_value=False,
339
+ )(f)
340
+ if pdk_options:
341
+ f = option_group(
342
+ "PDK options",
343
+ o(
344
+ "--volare-pdk/--manual-pdk",
345
+ "--ciel-pdk/--manual-pdk",
346
+ "use_ciel",
347
+ is_eager=True,
348
+ default=volare_by_default,
349
+ help="Automatically use Ciel for PDK version installation and enablement. Set --manual if you want to use a custom PDK version.",
350
+ ),
351
+ o(
352
+ "--pdk-root",
353
+ type=Path(
354
+ file_okay=False,
355
+ dir_okay=True,
356
+ ),
357
+ is_eager=True,
358
+ default=os.environ.pop("PDK_ROOT", None),
359
+ help="Override Ciel PDK root folder. Required if Ciel is not installed, but a default value can also be set via the environment variable PDK_ROOT.",
360
+ ),
361
+ o(
362
+ "-p",
363
+ "--pdk",
364
+ type=str,
365
+ default=os.environ.pop("PDK", "sky130A"),
366
+ help="The process design kit to use.",
367
+ ),
368
+ o(
369
+ "-s",
370
+ "--scl",
371
+ type=str,
372
+ default=os.environ.pop("STD_CELL_LIBRARY", None),
373
+ help="The standard cell library to use. If None, the PDK's default standard cell library is used.",
374
+ ),
375
+ )(f)
376
+ if jobs:
377
+ f = o(
378
+ "-j",
379
+ "--jobs",
380
+ type=int,
381
+ default=_get_process_limit(),
382
+ help="The maximum number of threads or processes that can be used by LibreLane.",
383
+ callback=set_worker_count_cb,
384
+ expose_value=False,
385
+ )(f)
386
+ if enable_initial_state_element:
387
+ f = o(
388
+ "-e",
389
+ "--initial-state-element-override",
390
+ type=str,
391
+ multiple=True,
392
+ default=(),
393
+ help="Elements to override in the used initial state in the format DESIGN_FORMAT_ID=PATH",
394
+ )(f)
395
+ if accept_config_files:
396
+ f = argument(
397
+ "config_files",
398
+ nargs=-1,
399
+ type=Path(
400
+ exists=True,
401
+ file_okay=True,
402
+ dir_okay=True,
403
+ ),
404
+ )(f)
405
+ if pdk_options:
406
+
407
+ @wraps(f)
408
+ def pdk_resolve_wrapper(
409
+ *args,
410
+ pdk_root: Optional[str],
411
+ pdk: str,
412
+ scl: Optional[str],
413
+ use_ciel: bool,
414
+ **kwargs,
415
+ ) -> str:
416
+ if not use_ciel:
417
+ if pdk_root is None:
418
+ err("Argument --pdk-root must be present with --manual-pdk.")
419
+ exit(1)
420
+ else:
421
+ import ciel
422
+ from ciel.source import StaticWebDataSource
423
+
424
+ opdks_rev = volare_pdk_override or get_opdks_rev()
425
+ ciel_home = ciel.get_ciel_home(pdk_root)
426
+
427
+ include_libraries = ["default"]
428
+ if scl is not None:
429
+ include_libraries.append(scl)
430
+
431
+ pdk_family = None
432
+ if family := ciel.Family.by_name.get(pdk):
433
+ pdk = family.default_variant
434
+ pdk_family = family.name
435
+ verbose(f"Resolved PDK variant {family.default_variant}.")
436
+ else:
437
+ for family in ciel.Family.by_name.values():
438
+ if pdk in family.variants:
439
+ pdk_family = family.name
440
+ break
441
+
442
+ if pdk_family is None:
443
+ err(f"Could not resolve the PDK '{pdk}'.")
444
+ exit(1)
445
+
446
+ version = ciel.fetch(
447
+ ciel_home,
448
+ pdk_family,
449
+ opdks_rev,
450
+ data_source=StaticWebDataSource(
451
+ "https://fossi-foundation.github.io/ciel-releases"
452
+ ),
453
+ include_libraries=include_libraries,
454
+ )
455
+ pdk_root = version.get_dir(ciel_home)
456
+
457
+ return f(*args, pdk_root=pdk_root, pdk=pdk, scl=scl, **kwargs)
458
+
459
+ return pdk_resolve_wrapper
460
+ else:
461
+ return f
462
+
463
+ return decorate