librelane 3.0.0.dev26__py3-none-any.whl → 3.0.0.dev28__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.

@@ -32,7 +32,7 @@ from .misc import (
32
32
  idem,
33
33
  get_librelane_root,
34
34
  get_script_dir,
35
- get_opdks_rev,
35
+ get_pdk_hash,
36
36
  slugify,
37
37
  protected,
38
38
  final,
@@ -158,7 +158,8 @@ def _compare_metric_folders(
158
158
  continue
159
159
  basename = basename[: -len(".metrics.json")]
160
160
 
161
- parts = basename.split("-", maxsplit=2)
161
+ # We have to rsplit, since ihp-sg13g2 contains a "-"
162
+ parts = basename.rsplit("-", maxsplit=2)
162
163
  if len(parts) != 3:
163
164
  raise ValueError(
164
165
  f"Invalid filename {basename}: not in the format {{pdk}}-{{scl}}-{{design_name}}"
librelane/common/misc.py CHANGED
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +20,7 @@ import os
16
20
  import re
17
21
  import glob
18
22
  import gzip
23
+ import yaml
19
24
  import typing
20
25
  import pathlib
21
26
  import fnmatch
@@ -37,6 +42,7 @@ import httpx
37
42
 
38
43
  from ..__version__ import __version__
39
44
  from .types import AnyPath, Path
45
+ from ..logging import err
40
46
 
41
47
  T = TypeVar("T")
42
48
 
@@ -68,15 +74,21 @@ def get_script_dir() -> str:
68
74
  )
69
75
 
70
76
 
71
- def get_opdks_rev() -> str:
77
+ def get_pdk_hash(pdk_variant) -> str:
72
78
  """
73
- Gets the Open_PDKs revision confirmed compatible with this version of LibreLane.
79
+ Gets the PDK version hash confirmed compatible with this version of LibreLane.
74
80
  """
75
- return (
76
- open(os.path.join(get_librelane_root(), "open_pdks_rev"), encoding="utf8")
77
- .read()
78
- .strip()
81
+
82
+ with open(os.path.join(get_librelane_root(), "pdk_hashes.yaml"), "r") as file:
83
+ pdk_hashes = yaml.safe_load(file)
84
+ for pdk_family in pdk_hashes:
85
+ if pdk_family in pdk_variant:
86
+ return pdk_hashes[pdk_family]
87
+
88
+ err(
89
+ f"Could not find a PDK family for '{pdk_variant}'. Please specify a PDK manually with '--manual-pdk'."
79
90
  )
91
+ exit(1)
80
92
 
81
93
 
82
94
  # The following code snippet has been adapted under the following license:
librelane/common/tcl.py CHANGED
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,12 +72,50 @@ class TclUtils(object):
68
72
  if value is not None:
69
73
  env_out[match.group(1)] = value
70
74
 
75
+ def py_dict(command, target=None, *args):
76
+ if command == "set":
77
+ if match := _env_rx.fullmatch(target):
78
+
79
+ if len(args) > 1:
80
+ value = args[-1]
81
+ keys = args[:-1]
82
+
83
+ # Create new dict if it does not exist
84
+ if not match.group(1) in env_out:
85
+ env_out[match.group(1)] = {}
86
+
87
+ # set ::env(...) [dict create]
88
+ # will create an empty string ""
89
+ # convert into an empty dictionary
90
+ if env_out[match.group(1)] == "":
91
+ env_out[match.group(1)] = {}
92
+
93
+ # Set key value pair
94
+ cur_dict = env_out[match.group(1)]
95
+
96
+ # Create all nested dicts
97
+ for key in keys[:-1]:
98
+ if key in cur_dict:
99
+ cur_dict = cur_dict[key]
100
+ else:
101
+ cur_dict[key] = {}
102
+ cur_dict = cur_dict[key]
103
+
104
+ # Finally set the value
105
+ cur_dict[keys[-1]] = value
106
+
71
107
  py_set_name = interpreter.register(py_set)
108
+ py_dict_name = interpreter.register(py_dict)
72
109
  interpreter.call("rename", py_set_name, "_py_set")
73
110
  interpreter.call("rename", "set", "_orig_set")
111
+ interpreter.call("rename", py_dict_name, "_py_dict")
112
+ interpreter.call("rename", "dict", "_orig_dict")
74
113
  interpreter.eval(
75
114
  "proc set args { _py_set {*}$args; tailcall _orig_set {*}$args; }"
76
115
  )
116
+ interpreter.eval(
117
+ "proc dict args { _py_dict {*}$args; tailcall _orig_dict {*}$args; }"
118
+ )
77
119
 
78
120
  interpreter.eval(tcl_in)
79
121
 
librelane/config/flow.py CHANGED
@@ -195,6 +195,13 @@ scl_variables = [
195
195
  "Path(s) to cells' SPICE model(s)",
196
196
  pdk=True,
197
197
  ),
198
+ Variable(
199
+ "CELL_CDLS",
200
+ Optional[List[Path]],
201
+ description="A circuit-design language view of the standard cell library.",
202
+ pdk=True,
203
+ deprecated_names=["STD_CELL_LIBRARY_CDL"],
204
+ ),
198
205
  Variable(
199
206
  "SYNTH_EXCLUDED_CELL_FILE",
200
207
  Path,
@@ -424,6 +431,11 @@ option_variables = [
424
431
  Optional[List[Path]],
425
432
  "Specifies miscellaneous SPICE models to be loaded indiscriminately whenever SPICE models are loaded.",
426
433
  ),
434
+ Variable(
435
+ "EXTRA_CDLS",
436
+ Optional[List[Path]],
437
+ "Specifies miscellaneous CDL netlists to be loaded indiscriminately whenever CDL netlists are loaded.",
438
+ ),
427
439
  Variable(
428
440
  "EXTRA_LIBS",
429
441
  Optional[List[Path]],
librelane/flows/cli.py CHANGED
@@ -34,7 +34,7 @@ from cloup.constraints import (
34
34
  from cloup.typing import Decorator
35
35
 
36
36
  from .flow import Flow
37
- from ..common import set_tpe, cli, get_opdks_rev, _get_process_limit
37
+ from ..common import set_tpe, cli, get_pdk_hash, _get_process_limit
38
38
  from ..logging import set_log_level, verbose, err, options, LogLevels
39
39
  from ..state import State, InvalidState
40
40
 
@@ -421,7 +421,7 @@ def cloup_flow_opts(
421
421
  import ciel
422
422
  from ciel.source import StaticWebDataSource
423
423
 
424
- opdks_rev = volare_pdk_override or get_opdks_rev()
424
+ opdks_rev = volare_pdk_override or get_pdk_hash(pdk)
425
425
  ciel_home = ciel.get_ciel_home(pdk_root)
426
426
 
427
427
  include_libraries = ["default"]
@@ -0,0 +1,3 @@
1
+ sky130: 8afc8346a57fe1ab7934ba5a6056ea8b43078e71
2
+ gf180mcu: 8afc8346a57fe1ab7934ba5a6056ea8b43078e71
3
+ ihp-sg13g2: cb7daaa8901016cf7c5d272dfa322c41f024931f
@@ -90,6 +90,13 @@ import click
90
90
  "input",
91
91
  type=click.Path(exists=True, file_okay=True, dir_okay=False),
92
92
  )
93
+ @click.option(
94
+ "--conflict-resolution",
95
+ "conflict_resolution",
96
+ type=str,
97
+ default="RenameCell",
98
+ help="Cell conflict resolution handling.",
99
+ )
93
100
  def stream_out(
94
101
  output: str,
95
102
  input_lefs: Tuple[str, ...],
@@ -100,6 +107,7 @@ def stream_out(
100
107
  seal_gds: Optional[str],
101
108
  design_name: str,
102
109
  input: str,
110
+ conflict_resolution: str,
103
111
  ): # Load technology file
104
112
  try:
105
113
  tech = pya.Technology()
@@ -109,6 +117,22 @@ def stream_out(
109
117
  layout_options.lefdef_config.lef_files = list(input_lefs)
110
118
  layout_options.lefdef_config.map_file = lym
111
119
 
120
+ cell_conflict_resolution = {
121
+ "AddToCell": pya.LoadLayoutOptions.CellConflictResolution.AddToCell,
122
+ "OverwriteCell": pya.LoadLayoutOptions.CellConflictResolution.OverwriteCell,
123
+ "RenameCell": pya.LoadLayoutOptions.CellConflictResolution.RenameCell,
124
+ "SkipNewCell": pya.LoadLayoutOptions.CellConflictResolution.SkipNewCell,
125
+ }.get(conflict_resolution)
126
+
127
+ if cell_conflict_resolution is None:
128
+ print(
129
+ f"[ERROR] Unknown conflict resolution: '{conflict_resolution}'.",
130
+ file=sys.stderr,
131
+ )
132
+ exit(1)
133
+ else:
134
+ layout_options.cell_conflict_resolution = cell_conflict_resolution
135
+
112
136
  # Load def file
113
137
  main_layout = pya.Layout()
114
138
  # main_layout.load_layer_props(props_file)
@@ -126,7 +150,7 @@ def stream_out(
126
150
  # Load in the gds to merge
127
151
  print("[INFO] Merging GDS files…")
128
152
  for gds in input_gds_files:
129
- main_layout.read(gds)
153
+ main_layout.read(gds, layout_options)
130
154
 
131
155
  # Copy the top level only to a new layout
132
156
  print(f"[INFO] Copying top level cell '{design_name}'…")
@@ -138,7 +162,7 @@ def stream_out(
138
162
  print("[INFO] Checking for missing GDS…")
139
163
  missing_gds = False
140
164
  for i in top_only_layout.each_cell():
141
- if i.is_empty():
165
+ if i.is_ghost_cell():
142
166
  missing_gds = True
143
167
  print(
144
168
  f"[ERROR] LEF Cell '{i.name}' has no matching GDS cell.",
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  set f [open $::env(STEP_DIR)/cif_scale.txt "w"]
15
- puts $f "[magic::i2u 1]"
15
+ puts $f [expr {((round([magic::cif scale output] * 10000)) / 10000.0) * 1}]
16
16
  close $f
17
17
 
18
18
  if { $::env(MAGIC_EXT_USE_GDS) } {
@@ -0,0 +1,23 @@
1
+ #
2
+ # Write CDL netlist of the current design
3
+ #
4
+
5
+ # Load design database
6
+ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
7
+ read_current_odb
8
+
9
+ # Collect masters CDL
10
+ set masters {}
11
+
12
+ foreach cdl $::env(CELL_CDLS) {
13
+ lappend masters $cdl
14
+ }
15
+
16
+ if { [info exist ::env(EXTRA_CDLS)] } {
17
+ foreach cdl $::env(EXTRA_CDLS) {
18
+ lappend masters $cdl
19
+ }
20
+ }
21
+
22
+ # Write only the CDL
23
+ write_cdl -include_fillers -masters "$masters" $::env(STEP_DIR)/$::env(DESIGN_NAME).cdl
@@ -38,7 +38,7 @@ def json_header(
38
38
  defines = (
39
39
  (config["VERILOG_DEFINES"] or [])
40
40
  + [
41
- f"PDK_{config['PDK']}",
41
+ f"PDK_{config['PDK'].replace('-','_')}",
42
42
  f"SCL_{config['STD_CELL_LIBRARY']}",
43
43
  "__librelane__",
44
44
  "__pnr__",
@@ -227,7 +227,7 @@ def synthesize(
227
227
 
228
228
  includes = config.get("VERILOG_INCLUDE_DIRS") or []
229
229
  defines = (config.get("VERILOG_DEFINES") or []) + [
230
- f"PDK_{config['PDK']}",
230
+ f"PDK_{config['PDK'].replace('-','_')}",
231
231
  f"SCL_{config['STD_CELL_LIBRARY']}",
232
232
  "__librelane__",
233
233
  "__pnr__",
@@ -239,6 +239,13 @@ DesignFormat(
239
239
  alts=["SPICE"],
240
240
  ).register()
241
241
 
242
+ DesignFormat(
243
+ "cdl",
244
+ "cdl",
245
+ "Circuit Design Language",
246
+ alts=["CDL"],
247
+ ).register()
248
+
242
249
  DesignFormat(
243
250
  "gds",
244
251
  "gds",
librelane/steps/cvc_rv.py CHANGED
@@ -16,7 +16,7 @@ import re
16
16
  import json
17
17
  from enum import Enum
18
18
  from io import StringIO, TextIOWrapper
19
- from typing import List, Optional, Tuple
19
+ from typing import Optional, Tuple
20
20
 
21
21
  from .step import StepException, ViewsUpdate, MetricsUpdate, Step
22
22
  from ..common import Path
@@ -124,13 +124,6 @@ class ERC(Step):
124
124
  description="",
125
125
  pdk=True,
126
126
  ),
127
- Variable(
128
- "CELL_CDLS",
129
- List[Path],
130
- description="A circuit-design language view of the standard cell library.",
131
- pdk=True,
132
- deprecated_names=["STD_CELL_LIBRARY_CDL"],
133
- ),
134
127
  ]
135
128
 
136
129
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +23,8 @@ import shutil
19
23
  import subprocess
20
24
  from os.path import abspath
21
25
  from base64 import b64encode
22
- from typing import Any, Dict, Optional, List, Sequence, Tuple, Union
26
+ from tempfile import NamedTemporaryFile
27
+ from typing import Any, Dict, Optional, List, Literal, Sequence, Tuple, Union
23
28
 
24
29
  from .step import ViewsUpdate, MetricsUpdate, Step, StepError, StepException
25
30
 
@@ -196,6 +201,17 @@ class StreamOut(KLayoutStep):
196
201
  inputs = [DesignFormat.DEF]
197
202
  outputs = [DesignFormat.GDS, DesignFormat.KLAYOUT_GDS]
198
203
 
204
+ config_vars = KLayoutStep.config_vars + [
205
+ Variable(
206
+ "KLAYOUT_CONFLICT_RESOLUTION",
207
+ Optional[
208
+ Literal["AddToCell", "OverwriteCell", "RenameCell", "SkipNewCell"]
209
+ ],
210
+ "Specifies the conflict resolution if a cell name conflict arises.",
211
+ default="RenameCell",
212
+ ),
213
+ ]
214
+
199
215
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
200
216
  views_updates: ViewsUpdate = {}
201
217
 
@@ -218,6 +234,8 @@ class StreamOut(KLayoutStep):
218
234
  abspath(klayout_gds_out),
219
235
  "--top",
220
236
  self.config["DESIGN_NAME"],
237
+ "--conflict-resolution",
238
+ self.config["KLAYOUT_CONFLICT_RESOLUTION"],
221
239
  ]
222
240
  + self.get_cli_args(include_lefs=True, include_gds=True),
223
241
  env=env,
@@ -431,10 +449,77 @@ class DRC(KLayoutStep):
431
449
  )
432
450
  return subprocess_result["generated_metrics"]
433
451
 
452
+ def run_ihp_sg13g2(self, state_in: State, **kwargs) -> MetricsUpdate:
453
+ kwargs, env = self.extract_env(kwargs)
454
+
455
+ drc_script_path = self.config["KLAYOUT_DRC_RUNSET"]
456
+
457
+ reports_dir = os.path.join(self.step_dir, "reports")
458
+ mkdirp(reports_dir)
459
+ xml_report = os.path.join(reports_dir, "drc_violations.klayout.xml")
460
+ json_report = os.path.join(reports_dir, "drc_violations.klayout.json")
461
+
462
+ input_view = state_in[DesignFormat.GDS]
463
+ assert isinstance(input_view, Path)
464
+
465
+ opts = []
466
+ for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
467
+ opts.extend(
468
+ [
469
+ "-rd",
470
+ f"{k}={v}",
471
+ ]
472
+ )
473
+
474
+ threads = self.config["KLAYOUT_DRC_THREADS"] or str(_get_process_limit())
475
+ if threads != "1":
476
+ opts.extend(
477
+ [
478
+ "-rd",
479
+ f"threads={threads}",
480
+ ]
481
+ )
482
+
483
+ info(f"Running KLayout DRC with {threads} threads…")
484
+
485
+ # Not pya script - DRC script is not part of OpenLane
486
+ self.run_subprocess(
487
+ [
488
+ "klayout",
489
+ "-b",
490
+ "-zz",
491
+ "-r",
492
+ drc_script_path,
493
+ "-rd",
494
+ f"in_gds={abspath(input_view)}",
495
+ "-rd",
496
+ f"report_file={abspath(xml_report)}",
497
+ *opts,
498
+ ]
499
+ )
500
+
501
+ subprocess_result = self.run_pya_script(
502
+ [
503
+ "python3",
504
+ os.path.join(
505
+ get_script_dir(),
506
+ "klayout",
507
+ "xml_drc_report_to_json.py",
508
+ ),
509
+ f"--xml-file={abspath(xml_report)}",
510
+ f"--json-file={abspath(json_report)}",
511
+ ],
512
+ env=env,
513
+ log_to=os.path.join(self.step_dir, "xml_drc_report_to_json.log"),
514
+ )
515
+ return subprocess_result["generated_metrics"]
516
+
434
517
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
435
518
  metrics_updates: MetricsUpdate = {}
436
519
  if self.config["PDK"] in ["sky130A", "sky130B"]:
437
520
  metrics_updates = self.run_sky130(state_in, **kwargs)
521
+ elif self.config["PDK"] in ["ihp-sg13g2"]:
522
+ metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
438
523
  else:
439
524
  self.warn(
440
525
  f"KLayout DRC is not supported for the {self.config['PDK']} PDK. This step will be skipped."
@@ -443,6 +528,126 @@ class DRC(KLayoutStep):
443
528
  return {}, metrics_updates
444
529
 
445
530
 
531
+ @Step.factory.register()
532
+ class LVS(KLayoutStep):
533
+ id = "KLayout.LVS"
534
+ name = "Layout Versus Schematic (KLayout)"
535
+
536
+ inputs = [
537
+ DesignFormat.CDL,
538
+ DesignFormat.GDS,
539
+ ]
540
+ outputs = [DesignFormat.SPICE]
541
+
542
+ config_vars = KLayoutStep.config_vars + [
543
+ Variable(
544
+ "KLAYOUT_LVS_SCRIPT",
545
+ Optional[Path],
546
+ "A path to KLayout LVS script.",
547
+ pdk=True,
548
+ ),
549
+ Variable(
550
+ "KLAYOUT_LVS_OPTIONS",
551
+ Optional[Dict[str, Union[bool, int, str]]],
552
+ "Options passed directly to the KLayout LVS script. They vary from one PDK to another.",
553
+ pdk=True,
554
+ ),
555
+ ]
556
+
557
+ def run_ihp_sg13g2(
558
+ self, state_in: State, **kwargs
559
+ ) -> Tuple[ViewsUpdate, MetricsUpdate]:
560
+ kwargs, env = self.extract_env(kwargs)
561
+
562
+ lvs_script_path = self.config["KLAYOUT_LVS_SCRIPT"]
563
+
564
+ reports_dir = os.path.join(self.step_dir, "reports")
565
+ mkdirp(reports_dir)
566
+ lvsdb_report = os.path.join(reports_dir, "lvs.klayout.lvsdb")
567
+
568
+ input_view_gds = state_in[DesignFormat.GDS]
569
+ input_view_cdl = state_in[DesignFormat.CDL]
570
+ assert isinstance(input_view_gds, Path)
571
+ assert isinstance(input_view_cdl, Path)
572
+
573
+ output_spice = os.path.join(
574
+ self.step_dir,
575
+ f"{self.config['DESIGN_NAME']}.{DesignFormat.SPICE.value.extension}",
576
+ )
577
+
578
+ with NamedTemporaryFile("w") as f:
579
+ # Merge all CDL inputs
580
+ cdl_lst = [input_view_cdl]
581
+ cdl_lst.extend(self.config["CELL_CDLS"] or [])
582
+ cdl_lst.extend(self.config["EXTRA_CDLS"] or [])
583
+
584
+ for fn in cdl_lst:
585
+ with open(fn, "r") as cdl_fh:
586
+ f.write(cdl_fh.read())
587
+
588
+ opts = []
589
+ for k, v in self.config["KLAYOUT_LVS_OPTIONS"].items():
590
+ opts.extend(
591
+ [
592
+ "-rd",
593
+ f"{k}={v}",
594
+ ]
595
+ )
596
+
597
+ # Not pya script - LVS script is not part of LibreLane
598
+ subprocess_result = self.run_subprocess(
599
+ [
600
+ "klayout",
601
+ "-b",
602
+ "-zz",
603
+ "-r",
604
+ lvs_script_path,
605
+ "-rd",
606
+ f"input={abspath(input_view_gds)}",
607
+ "-rd",
608
+ f"schematic={abspath(f.name)}",
609
+ "-rd",
610
+ f"report={abspath(lvsdb_report)}",
611
+ "-rd",
612
+ f"target_netlist={abspath(output_spice)}",
613
+ ]
614
+ + opts,
615
+ env=env,
616
+ )
617
+
618
+ with open(subprocess_result["log_path"]) as fh:
619
+ for line in fh:
620
+ if "INFO : Congratulations! Netlists match" in line:
621
+ ok = True
622
+ break
623
+ elif "ERROR : Netlists don't match" in line:
624
+ ok = False
625
+ break
626
+ else:
627
+ ok = False
628
+
629
+ views_updates: ViewsUpdate = {
630
+ DesignFormat.SPICE: Path(output_spice),
631
+ }
632
+ metrics_updates: MetricsUpdate = {
633
+ "design__lvs_error__count": 0 if ok else 1,
634
+ }
635
+
636
+ return views_updates, metrics_updates
637
+
638
+ def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
639
+ metrics_updates: MetricsUpdate = {}
640
+ views_updates: ViewsUpdate = {}
641
+ if self.config["PDK"] in ["ihp-sg13g2"]:
642
+ views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
643
+ else:
644
+ self.warn(
645
+ f"KLayout LVS is not supported for the {self.config['PDK']} PDK. This step will be skipped."
646
+ )
647
+
648
+ return views_updates, metrics_updates
649
+
650
+
446
651
  @Step.factory.register()
447
652
  class OpenGUI(KLayoutStep):
448
653
  """
@@ -480,7 +685,7 @@ class OpenGUI(KLayoutStep):
480
685
 
481
686
  layout = state_in[DesignFormat.DEF]
482
687
  if self.config["KLAYOUT_GUI_USE_GDS"]:
483
- if gds := state_in[DesignFormat.GDS]:
688
+ if gds := state_in.get(DesignFormat.GDS):
484
689
  layout = gds
485
690
  assert isinstance(layout, Path)
486
691
 
@@ -2188,6 +2188,20 @@ class WriteViews(OpenROADStep):
2188
2188
  return os.path.join(get_script_dir(), "openroad", "write_views.tcl")
2189
2189
 
2190
2190
 
2191
+ @Step.factory.register()
2192
+ class WriteCDL(OpenROADStep):
2193
+ """
2194
+ Write CDL view of an ODB design
2195
+ """
2196
+
2197
+ id = "OpenROAD.WriteCDL"
2198
+ name = "Write CDL"
2199
+ outputs = [DesignFormat.CDL]
2200
+
2201
+ def get_script_path(self):
2202
+ return os.path.join(get_script_dir(), "openroad", "write_cdl.tcl")
2203
+
2204
+
2191
2205
  # Resizer Steps
2192
2206
 
2193
2207
 
librelane/steps/yosys.py CHANGED
@@ -48,7 +48,7 @@ def _generate_read_deps(
48
48
  commands = ""
49
49
 
50
50
  synth_defines = [
51
- f"PDK_{config['PDK']}",
51
+ f"PDK_{config['PDK'].replace('-','_')}",
52
52
  f"SCL_{config['STD_CELL_LIBRARY']}",
53
53
  "__librelane__",
54
54
  "__pnr__",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: librelane
3
- Version: 3.0.0.dev26
3
+ Version: 3.0.0.dev28
4
4
  Summary: An infrastructure for implementing chip design flows
5
5
  Home-page: https://github.com/librelane/librelane
6
6
  License: Apache-2.0
@@ -1,25 +1,25 @@
1
1
  librelane/__init__.py,sha256=EMpoZrRmS_wsweKjhyAg52OXCK7HWQ8o8CVrYaX4ub0,1220
2
2
  librelane/__main__.py,sha256=Zq2h2ZTQqA0T7qpGFELJ1bzVQnv-951nnhJ0-9WzNaM,14541
3
3
  librelane/__version__.py,sha256=dbE4stCACDmIoxgKksesAkTa-_hi5dW6nPLWw9Pfq3Q,1486
4
- librelane/common/__init__.py,sha256=QhzRvLXLR2cGdYenayWYmCfgkTS836dWW41Ve1Wa5IE,1551
4
+ librelane/common/__init__.py,sha256=FYBKTUKpAwexQSgCaH_IfbozmDk0hA1ITpl66J8Qcwo,1550
5
5
  librelane/common/cli.py,sha256=xi48GBGHRsYrLGwx40ARwpykHx7GnuHbJjHxjOwtZ5Y,2349
6
6
  librelane/common/drc.py,sha256=l1quZbHXGb7yjKCO5IFn-Xxf_zIx4f6kxqpNm3YmpOs,12809
7
7
  librelane/common/generic_dict.py,sha256=ASa5wtVcLuGlsBqGfLxLYXrYksqQB62iHljV04plIqI,10010
8
8
  librelane/common/metrics/__init__.py,sha256=nzdmeia1fN4CDPT604v-OHaBVydz-M4hz232g-jxJ6M,1521
9
- librelane/common/metrics/__main__.py,sha256=VfoOHFkGXtei6GLkPUD42X6io8QKFCHhxLMWOXPz_5E,12473
9
+ librelane/common/metrics/__main__.py,sha256=1w23V_1-f0WUSfxG36ewNHctgPisQFFG4p-R-wZsyNs,12539
10
10
  librelane/common/metrics/library.py,sha256=CG7rubLdjuCQL9-9bzAC-64hf-KlH-iu_Fg0oKuesqs,7373
11
11
  librelane/common/metrics/metric.py,sha256=h3Xd26z5M80IJgVmmrBTjKcdGLb4I0wyjM-H4jdyi_0,6990
12
12
  librelane/common/metrics/util.py,sha256=Bl_9znlot7-Os2VigYLSmMf56aAkGdv3evWz9vfK7K4,9344
13
- librelane/common/misc.py,sha256=2zj62QbSuYaD2iYqGnM7vFR3ga41E3TxZpOOBYYIka8,13257
13
+ librelane/common/misc.py,sha256=vjSfFT2KV5TNTxqeLt5EFqcprRrjrgNvgOJpBl7JpM4,13627
14
14
  librelane/common/ring_buffer.py,sha256=DGFen9y0JOmiL7E27tmzDTVSJKZtV-waF9hl5Rz9uek,1898
15
- librelane/common/tcl.py,sha256=G0__oR6azVCS2Aue87zboba7vAR7v-SVQeUbqfviiDA,2709
15
+ librelane/common/tcl.py,sha256=AfTxbSLA0VUXVMMwoAQndyQTcEZQoQfMa4FFizZiEgU,4341
16
16
  librelane/common/toolbox.py,sha256=ijR__rVqQ_nJtfm34H-VdSCIeArKns7lVAc1TcTUSsQ,20975
17
17
  librelane/common/tpe.py,sha256=Txj0fVscXSDJTYmEKZ2ESFHOeqrhHnaPPiwWBgyx4g8,1285
18
18
  librelane/common/types.py,sha256=xo_OKq-2ue7JVpyQb6oUu6JuVSnLNEFKQCPBqNhZnQ4,3509
19
19
  librelane/config/__init__.py,sha256=lbJmD5CbrrrnaNdIUWqFIK488ea0uyej3iExh-9mkgE,1107
20
20
  librelane/config/__main__.py,sha256=NsJGoIOb950mdXql1zmzSq10wuFovK9NGWm011NNJ3A,4474
21
21
  librelane/config/config.py,sha256=bAxB0qpw95YoLGmMjvxAwrX1hcpHRvNhH7wjQdyW-DE,35031
22
- librelane/config/flow.py,sha256=RS8uspcrepl8GT5SsWrBQ-kmssO4c15_lrc2nBPVK5M,16482
22
+ librelane/config/flow.py,sha256=DLB1h3UX_0cWgJblAmCSrsWL6dV0SEx0mz4ohIsV2uo,16892
23
23
  librelane/config/pdk_compat.py,sha256=ofqYuD-MgTcfvPVXpGJo8H1GKzCvN6sxHsK_OqCVXa8,12870
24
24
  librelane/config/preprocessor.py,sha256=ATi29SHz0_OBq1IqUkGxvhHUDKB5z5jO0KqvoQXg8R8,14913
25
25
  librelane/config/removals.py,sha256=vxqTuRTJ0jt2TX4KmFZCZPTwghDFkCVjIhF2iReHwJA,2958
@@ -42,7 +42,7 @@ librelane/examples/spm-user_project_wrapper/user_project_wrapper.v,sha256=zc6GC5
42
42
  librelane/flows/__init__.py,sha256=ghtmUG-taVpHJ3CKJRYZGn3dU0r93araT1EIGlBEsxg,896
43
43
  librelane/flows/builtins.py,sha256=tR14Qc1ZUey2w-Ar4DWOvxuP7LGPtMecCJq8WgcYJpk,773
44
44
  librelane/flows/classic.py,sha256=JB9gVgP2hHPhMuCJg7hvoj2BvJcvRec7suEXPgHmz14,10971
45
- librelane/flows/cli.py,sha256=P2LCFn5_RQ88yB0WuetpLAuWeKQXd-DrpCOMgnVh9Mg,16705
45
+ librelane/flows/cli.py,sha256=_aJjlalCsmUeLiqy1D8VFmBJ0dLelx24erqaK2q-AOs,16706
46
46
  librelane/flows/flow.py,sha256=qly_ENbw8zHSS6ubUY56JrCRjKnfuSoN78suz1k4chw,36997
47
47
  librelane/flows/misc.py,sha256=32Om3isexesfKKiJZCajNmINc-xdv7eVx_tgoh9SR6U,2015
48
48
  librelane/flows/optimizing.py,sha256=OwZz6WGmXpliwO8vtmhjKHD-kzDyNv-zoCECZIigXsI,6076
@@ -50,14 +50,14 @@ librelane/flows/sequential.py,sha256=kBpR9kxfEfdTaNy9Ter2KNQXkW6qojCwoBsFJBwTq6I
50
50
  librelane/flows/synth_explore.py,sha256=8mpeuG6oxeEXVQi4NwS4I415eCu7Ak6DN4oK30h1eCQ,7418
51
51
  librelane/logging/__init__.py,sha256=mrTnzjpH6AOu2CiDZYfOMCVByAS2Xeg9HS4FJyXsJOE,1043
52
52
  librelane/logging/logger.py,sha256=kA61TGsR00Fi6kQSxgTC1pHpS_-zqC1PdQnYqnk2TWY,8632
53
- librelane/open_pdks_rev,sha256=_q6FiO0UljepWU99r9IgkbLrKLDIPbO-80--OFWrZxA,41
53
+ librelane/pdk_hashes.yaml,sha256=wHPz6Ze4e1uhZTo7IKS4wcmU6ShcZdBtHcdACP5tYNI,153
54
54
  librelane/plugins.py,sha256=G5o2h1LT4a1LO1Q0gKXXuhqcEdjdTFkYU8QUSg2D2eM,820
55
55
  librelane/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  librelane/scripts/base.sdc,sha256=zGPSBLDt-5dbYvm3AGbjsZsyKxjFOc4znyjwZM4wIps,3145
57
57
  librelane/scripts/klayout/Readme.md,sha256=hJs44QIB3lHPD3E-Z-tbAC1RBmt5Fl1khzQF2gRewLE,76
58
58
  librelane/scripts/klayout/open_design.py,sha256=0cBELVhSBGmp_KxDN0vsCEh6x1JPW0Q6cXkBd3S-XKk,2395
59
59
  librelane/scripts/klayout/render.py,sha256=FH-rp7Q363T0gD9_p-n4_suya4hfAPzL2jZIF0fmLwA,3833
60
- librelane/scripts/klayout/stream_out.py,sha256=0GALkaKkrjcnASng32Fxq93dsgC9Fi4Rr_qRBT-eFGU,5867
60
+ librelane/scripts/klayout/stream_out.py,sha256=MLpe0oGl7oy2bD4ddk0ixRJgsiBUDzEv_UPwYspgT3s,6796
61
61
  librelane/scripts/klayout/xml_drc_report_to_json.py,sha256=6nwTymQ1ypA5OgSvqySxzIWqDgGlW_1tlbtauc0BUdE,1412
62
62
  librelane/scripts/klayout/xor.drc,sha256=Nm_6JR_png-31uajL3DrW3dVGo7Kd6G-zS9RTftL25o,3131
63
63
  librelane/scripts/magic/Readme.md,sha256=NaQrlxY8l8GT-kokJNlMHeAR3PksWVbFpSznOWWshhw,126
@@ -66,7 +66,7 @@ librelane/scripts/magic/def/antenna_check.tcl,sha256=T_r1CWgySFVlLMcoTrNXQ_aMRs_
66
66
  librelane/scripts/magic/def/mag.tcl,sha256=PuL3MH6pmZP5Qh2cJ0GygWNzaYjdCSCoAbOli-JB4fs,707
67
67
  librelane/scripts/magic/def/mag_gds.tcl,sha256=fwtQR9zPZpWqVmmLb-1hzY4WMCr4gbA3S0pTZsS9sss,2144
68
68
  librelane/scripts/magic/drc.tcl,sha256=gPGyI96lR10dJXcJACajzHaHiT6ayAYPJqrmmuQkABc,2395
69
- librelane/scripts/magic/extract_spice.tcl,sha256=lFNXfjIIzAWb2wda9ZtBOecENOOXyFBsh9HgrPYf7VQ,2737
69
+ librelane/scripts/magic/extract_spice.tcl,sha256=-jDxVEGddch1YZLZXW1vFXhdLkeTjxk0d8eU1tBMBWc,2788
70
70
  librelane/scripts/magic/gds/drc_batch.tcl,sha256=O76rwxSrQgoCuoxk36tRBZkQaeMfJknlHrQA3mtU2JU,2198
71
71
  librelane/scripts/magic/gds/erase_box.tcl,sha256=wsVSwMlkZFJa_MEGNsdXLnXFvjZlrl_lzIWkJjcDBgg,929
72
72
  librelane/scripts/magic/gds/extras_mag.tcl,sha256=1raG0URUezUDEKkdDeJqdlS0Y5gb4IzQFnjFysHHlmU,1304
@@ -138,34 +138,35 @@ librelane/scripts/openroad/sta/check_macro_instances.tcl,sha256=j8DlW1wkVk5bLbG7
138
138
  librelane/scripts/openroad/sta/corner.tcl,sha256=0YAzHFGbs4zRsB5E7e8zdzFyLuzrpV1w_S2BgrLfqak,15235
139
139
  librelane/scripts/openroad/tapcell.tcl,sha256=4Ouy5U-_ct5Cfy3vuLQudWL0c1xWF_auLsr9rYh6dP4,1177
140
140
  librelane/scripts/openroad/ungpl.tcl,sha256=vhHxou1W3VROwJePoQzmWn0h0d5lQrrt1vofyt-Woek,761
141
+ librelane/scripts/openroad/write_cdl.tcl,sha256=uPO1IROPTr5NrW0-VZA8tXQD8aseGeXDXDsU8TX-9nQ,460
141
142
  librelane/scripts/openroad/write_views.tcl,sha256=-MxTJsB4EF7l5trDaZe-VBFjhfzqRt8F5_DZrADTs0U,892
142
143
  librelane/scripts/pyosys/construct_abc_script.py,sha256=3CCDz5ZTEPpWLco-OvikTmn361-BNitqjQE_-5zHm14,6733
143
- librelane/scripts/pyosys/json_header.py,sha256=C1BmKFRbwMknXV_RVp5QGbAxCwU6ElE6UIGRZceHQpI,2315
144
- librelane/scripts/pyosys/synthesize.py,sha256=2NZWdtskSRGUGghYLkw-LGdEH_IL9Vfl3NUD2GR3Kdk,16910
144
+ librelane/scripts/pyosys/json_header.py,sha256=gKla0V4tFhF5fR-zzudrTr6TjpqkV3c69PWk1fVfMgg,2332
145
+ librelane/scripts/pyosys/synthesize.py,sha256=soDbOObGdCix3zDUQFIF6FvZn6_mT_GonkvH5exGQiA,16927
145
146
  librelane/scripts/pyosys/ys_common.py,sha256=t5LLEYoy4cfCIeEaAo8Nr51rXtlI8ZPe1h_kSbrky5M,3891
146
147
  librelane/scripts/tclsh/hello.tcl,sha256=kkR3akY7QnGHYXsQODYwLkMkUEOgWcNFtzaMTTEV2bY,34
147
148
  librelane/state/__init__.py,sha256=DZ_RyKMr2oj4p5d32u8MmDKfCxR7OEdDw-1HWKTpatA,949
148
149
  librelane/state/__main__.py,sha256=Ici4Ejg1ICUZNSYZRguC3BfEk_wFxsmE0ag0Vv8iY1I,1679
149
- librelane/state/design_format.py,sha256=75-XXzCfk5HUAJQAcdpwiHYkweeR9NwaXKtubCV0dqg,6461
150
+ librelane/state/design_format.py,sha256=v1Nj-glM3Nc6SVXMZKanAMiaBjgDnW8KjAlmr_TiOqk,6560
150
151
  librelane/state/state.py,sha256=tYn2si8NlkVErOSWKfVhsgrMpyxeX2Hv9EAPsQBWx2c,11902
151
152
  librelane/steps/__init__.py,sha256=j3JYrdnWM74dYuEvE931oSrQI7FUz-hKWr8Mts8C0wg,1668
152
153
  librelane/steps/__main__.py,sha256=GQZiV4s-9GIF4AwP34W61zwgzMvPp-QTR4cNELi7r5c,13349
153
154
  librelane/steps/checker.py,sha256=HD5YFPAbHQKsFmBDrIAbo_0clZcCszNhIXb4lHaNIeQ,21629
154
155
  librelane/steps/common_variables.py,sha256=eih2eA1m0FpL8ydF5WWattwh_SxtzI55eb8gggJtBuY,12494
155
- librelane/steps/cvc_rv.py,sha256=TNnEQDJI5tEUq8OQelVmBWmNbLzygrvKsZ36utKDvp4,5543
156
- librelane/steps/klayout.py,sha256=EFtzu53bWm-Bg_xEovdR7fc1GbWTwqkcivtr1rivHWU,16615
156
+ librelane/steps/cvc_rv.py,sha256=qeroQPjidSAMYSp3nJNiQBYt8V73kkz3JK97uioo7J8,5294
157
+ librelane/steps/klayout.py,sha256=18B7trKjyD8HnGUVwrjQV8XRzGu298CuosM1WOzg9oM,23255
157
158
  librelane/steps/magic.py,sha256=m4cZH2VomJs0RudtV8avSaZVqRj1NP7Pm2P6qo2z2X0,20919
158
159
  librelane/steps/misc.py,sha256=8ubCvFeFEspXrgnzNWINY5-TXTyalNtlvcX8TSw0qdg,5685
159
160
  librelane/steps/netgen.py,sha256=R9sDWv-9wKMdi2rkuLQdOc4uLlbYhXcKKd6WsZsnLt0,8953
160
161
  librelane/steps/odb.py,sha256=-zsXi0jVdtfBfAJI0OC4x1jI_B2OX5YVn4uAn6NyFdk,38424
161
- librelane/steps/openroad.py,sha256=0wA8-fvtIDbaSteh8lY_VxW7cF_73MdNKqTvWc7Blf4,99284
162
+ librelane/steps/openroad.py,sha256=hgpqsVQi7tFRlj75zefQkD3Vdmq21ubZAFWyU12WxUg,99586
162
163
  librelane/steps/openroad_alerts.py,sha256=IJyB4piBDCKXhkJswHGMYCRDwbdQsR0GZlrGGDhmW6Q,3364
163
164
  librelane/steps/pyosys.py,sha256=LY7qqxkhjfoyBBR7vdkm7ylabbxMJDwIoYm7mAUbLVY,23348
164
165
  librelane/steps/step.py,sha256=THIxZkhtkNYt1iRgMduD0ywrOTCaV7cCfUB2EqXN6-k,55751
165
166
  librelane/steps/tclstep.py,sha256=8-zpYOo562E86nm7f4DiTqUsLKY0AFtEJgrp9CnWWDw,10083
166
167
  librelane/steps/verilator.py,sha256=MWx2TpLqYyea9_jSeLG9c2S5ujvYERQZRFNaMhfHxZE,7916
167
- librelane/steps/yosys.py,sha256=uC72fb1yFXyIxrtcRu5DxxR3hadG19SlGh668yjhWHc,12694
168
- librelane-3.0.0.dev26.dist-info/METADATA,sha256=ndJNvx1YIso3n8GZhhQLFStMDVNpsjMTJ562JZGLULs,6561
169
- librelane-3.0.0.dev26.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
170
- librelane-3.0.0.dev26.dist-info/entry_points.txt,sha256=GTBvXykNMMFsNKiJFgtEw7P1wb_VZIqVM35EFSpyZQE,263
171
- librelane-3.0.0.dev26.dist-info/RECORD,,
168
+ librelane/steps/yosys.py,sha256=lYdZPFvjcmdu_NE6rtB94_dysIK2qwGdGb480W6pg2w,12711
169
+ librelane-3.0.0.dev28.dist-info/METADATA,sha256=G4c7el3lW3tANOTRs4enKF5MHT-YYMOrBeLpARSsmIw,6561
170
+ librelane-3.0.0.dev28.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
171
+ librelane-3.0.0.dev28.dist-info/entry_points.txt,sha256=GTBvXykNMMFsNKiJFgtEw7P1wb_VZIqVM35EFSpyZQE,263
172
+ librelane-3.0.0.dev28.dist-info/RECORD,,
librelane/open_pdks_rev DELETED
@@ -1 +0,0 @@
1
- 0fe599b2afb6708d281543108caf8310912f54af