librelane 3.1.0.dev3__py3-none-any.whl → 3.1.0.dev4__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.
@@ -33,6 +33,7 @@ from .misc import (
33
33
  get_librelane_root,
34
34
  get_script_dir,
35
35
  get_pdk_hash,
36
+ get_ciel_pdk_hash,
36
37
  slugify,
37
38
  protected,
38
39
  final,
librelane/common/misc.py CHANGED
@@ -40,6 +40,7 @@ from typing import (
40
40
  )
41
41
 
42
42
  import httpx
43
+ from deprecated.sphinx import deprecated
43
44
 
44
45
  from ..__version__ import __version__
45
46
  from .types import AnyPath, Path
@@ -75,6 +76,11 @@ def get_script_dir() -> str:
75
76
  )
76
77
 
77
78
 
79
+ @deprecated(
80
+ version="3.1.0",
81
+ reason="Use get_ciel_pdk_hash, this method can force an exit in some codepaths",
82
+ action="once",
83
+ )
78
84
  def get_pdk_hash(pdk_variant) -> str:
79
85
  """
80
86
  Gets the PDK version hash confirmed compatible with this version of LibreLane.
@@ -92,6 +98,27 @@ def get_pdk_hash(pdk_variant) -> str:
92
98
  exit(1)
93
99
 
94
100
 
101
+ def get_ciel_pdk_hash(pdk_variant: str) -> str:
102
+ """
103
+ Gets the PDK version hash confirmed compatible with this version of LibreLane.
104
+
105
+ Requires ciel
106
+ """
107
+ import ciel
108
+
109
+ with open(os.path.join(get_librelane_root(), "pdk_hashes.yaml"), "r") as file:
110
+ pdk_hashes = yaml.safe_load(file)
111
+
112
+ pdk_family = ciel.resolve_pdk_family(pdk_variant)
113
+
114
+ if pdk_family not in pdk_hashes:
115
+ raise ValueError(
116
+ f"LibreLane does not have a validated version for Ciel PDK family {pdk_family}."
117
+ )
118
+
119
+ return pdk_hashes[pdk_family]
120
+
121
+
95
122
  # The following code snippet has been adapted under the following license:
96
123
  #
97
124
  # Copyright (c) Django Software Foundation and individual contributors.
@@ -367,6 +367,11 @@ class Toolbox(object):
367
367
  warn(f"Failed to generate preview: {e}.")
368
368
  return None
369
369
 
370
+ @deprecated(
371
+ version="3.1.0",
372
+ reason="No longer needed by internal LibreLane steps and will be removed in LibreLane 4.0.",
373
+ action="once",
374
+ )
370
375
  def remove_cells_from_lib(
371
376
  self,
372
377
  input_lib_files: FrozenSet[str],
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -815,7 +819,7 @@ class Config(GenericImmutableDict[str, Any]):
815
819
  try:
816
820
  import ciel
817
821
 
818
- pdk_root = ciel.get_ciel_home(pdk_root)
822
+ pdk_root = str(ciel.get_ciel_home(pdk_root))
819
823
  except ImportError:
820
824
  raise ValueError(
821
825
  "The pdk_root argument is required as Ciel is not installed."
librelane/config/flow.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Copyright 2025 LibreLane Contributors
2
2
  #
3
- # Adapted from OpenLane
3
+ # Adapted from OpenLane 2
4
4
  #
5
5
  # Copyright 2023 Efabless Corporation
6
6
  #
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023-2025 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -350,4 +354,20 @@ def migrate_old_config(config: Mapping[str, Any]) -> Dict[str, Any]:
350
354
  if "HEURISTIC_ANTENNA_THRESHOLD" not in config:
351
355
  new["HEURISTIC_ANTENNA_THRESHOLD"] = 130
352
356
 
357
+ # x7. KLAYOUT_DRC_OPTIONS to defines
358
+ if new["PDK"].startswith("sky130") and "KLAYOUT_DRC_OPTIONS" in new:
359
+ tcl_dict = new["KLAYOUT_DRC_OPTIONS"]
360
+ ws_rx = re.compile(r"\s+")
361
+ del new["KLAYOUT_DRC_OPTIONS"]
362
+ new["KLAYOUT_DRC_DEFINES"] = {}
363
+ # deliberately not checking for bad dicts or dicts that require quoting
364
+ # it's already overkill to assume people modified the PDK files here
365
+ #
366
+ # if someone complains we can parse a Tcl dict later
367
+ tcl_dict_entries = ws_rx.split(tcl_dict)
368
+ while len(tcl_dict_entries):
369
+ key = tcl_dict_entries.pop(0)
370
+ value = tcl_dict_entries.pop(0)
371
+ new["KLAYOUT_DRC_DEFINES"][key] = value
372
+
353
373
  return new
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
librelane/flows/cli.py CHANGED
@@ -43,7 +43,7 @@ from cloup.constraints import (
43
43
  from cloup.typing import Decorator
44
44
 
45
45
  from .flow import Flow
46
- from ..common import set_tpe, cli, get_pdk_hash, _get_process_limit
46
+ from ..common import set_tpe, cli, get_ciel_pdk_hash, _get_process_limit
47
47
  from ..logging import set_log_level, verbose, err, options, LogLevels
48
48
  from ..state import State, InvalidState
49
49
 
@@ -517,8 +517,7 @@ def cloup_flow_opts(
517
517
  import ciel
518
518
  from ciel.source import StaticWebDataSource
519
519
 
520
- opdks_rev = volare_pdk_override or get_pdk_hash(pdk)
521
- ciel_home = ciel.get_ciel_home(pdk_root)
520
+ ciel_home = str(ciel.get_ciel_home(pdk_root))
522
521
 
523
522
  include_libraries = ["default"]
524
523
  if scl is not None:
@@ -527,32 +526,35 @@ def cloup_flow_opts(
527
526
  if pad is not None:
528
527
  include_libraries.append(pad)
529
528
 
530
- pdk_family = None
531
- if family := ciel.Family.by_name.get(pdk):
532
- pdk = family.default_variant
533
- pdk_family = family.name
534
- verbose(f"Resolved PDK variant {family.default_variant}.")
535
- else:
536
- for family in ciel.Family.by_name.values():
537
- if pdk in family.variants:
538
- pdk_family = family.name
539
- break
540
-
541
- if pdk_family is None:
542
- err(f"Could not resolve the PDK '{pdk}'.")
529
+ selector = pdk
530
+
531
+ try:
532
+ pdk = ciel.resolve_pdk_variant(pdk)
533
+ if pdk != selector:
534
+ verbose(f"Resolved PDK variant {pdk}.")
535
+ except ValueError as e:
536
+ err(str(e))
537
+ err("If you're using a non-Ciel PDK, please pass --manual-pdk.")
538
+ exit(1)
539
+
540
+ try:
541
+ opdks_rev = volare_pdk_override or get_ciel_pdk_hash(pdk)
542
+ except ValueError as e:
543
+ err(str(e))
544
+ err("Please specify a PDK manually with '--manual-pdk'.")
543
545
  exit(1)
544
546
 
545
547
  try:
546
548
  version = ciel.fetch(
547
549
  ciel_home,
548
- pdk_family,
550
+ pdk, # only pull default libraries for resolved variant since we have a message saying "Resolved variant {pdk}..."
549
551
  opdks_rev,
550
552
  data_source=StaticWebDataSource(
551
553
  "https://fossi-foundation.github.io/ciel-releases"
552
554
  ),
553
555
  include_libraries=include_libraries,
554
556
  )
555
- pdk_root = version.get_dir(ciel_home)
557
+ pdk_root = str(version.get_dir(ciel_home))
556
558
  except ValueError as e:
557
559
  err(f"Failed to download PDK: {e}")
558
560
  exit(1)
@@ -79,6 +79,7 @@ class SynthesisExploration(Flow):
79
79
  options.set_condensed_mode(True)
80
80
 
81
81
  for strategy in [
82
+ "DEFAULT",
82
83
  "AREA 0",
83
84
  "AREA 1",
84
85
  "AREA 2",
librelane/pdk_hashes.yaml CHANGED
@@ -1,3 +1,4 @@
1
- sky130: 74c0e6b118a67d94c24172143d3bd597473fa63d
2
- gf180mcu: f6eeac7dad085ffcc829ccfd721f7b4ce39edcf7
3
- ihp-sg13g2: ee974c3adc69d0f36adbf20577079f0df419d702
1
+ sky130: 792ef67037d74c8c51811eab3ce23cf793491296
2
+ gf180mcu: 792ef67037d74c8c51811eab3ce23cf793491296
3
+ ihp-sg13: 89d42ee6d2fd9b50b86a1aada6fee6673c3e6008
4
+ freepdk45: 784b1a483a5f4de362d6f3629378de1199453f3c
@@ -65,7 +65,7 @@ def check_cells(odb_cells):
65
65
  }
66
66
  report.append(entry)
67
67
 
68
- return report
68
+ return report
69
69
 
70
70
 
71
71
  def get_top_level_cell(input_lefs, design_lef, cell_name):
@@ -562,7 +562,10 @@ def remove_obstructions(reader, input_lefs, obstructions):
562
562
  if (odb_layer, odb_bbox) == (layer, bbox):
563
563
  print(f"Removing obstruction on {layer} at {bbox} (DBU)…")
564
564
  found = True
565
- odb.dbObstruction_destroy(odb_obj)
565
+ if not odb_obj.isSystemReserved():
566
+ odb.dbObstruction_destroy(odb_obj)
567
+ else:
568
+ print("[WARNING] Obstruction is system-reserved.")
566
569
  if found:
567
570
  break
568
571
  if not found:
@@ -19,11 +19,23 @@ source $::env(_TCL_ENV_IN)
19
19
  source $::env(SCRIPTS_DIR)/openroad/common/set_global_connections.tcl
20
20
 
21
21
  namespace eval lln {
22
+ proc scene_name {scene} {
23
+ # OpenSTA >= 3.1 (commit 998806cb, 2026-06-30) bridges scenes as SWIG
24
+ # objects instead of strings. Older OpenSTA 3 bridges them as strings,
25
+ # in which case the value already is the name.
26
+ if { [sta::is_object $scene] } {
27
+ return [sta::get_property $scene name]
28
+ }
29
+ return $scene
30
+ }
22
31
  proc get_corner_names {} {
23
32
  # returns: names as a Tcl list, compatible with both OpenSTA 2 and 3
24
33
  if {[string length [namespace which sta::scenes]] != 0} {
25
- # scenes are bridged as a list of strings
26
- return [sta::scenes]
34
+ set result [list]
35
+ foreach scene [sta::scenes] {
36
+ lappend result [scene_name $scene]
37
+ }
38
+ return $result
27
39
  } else {
28
40
  # corners are not bridged as strings
29
41
  set result [list]
@@ -36,12 +48,14 @@ namespace eval lln {
36
48
  proc get_corner_dict {} {
37
49
  # returns: Tcl dictionary from corner names to whatever object is
38
50
  # interpreted as a corner for internal commands that expect corners:
39
- # - in OpenSTA 3, that's the scene's name again
51
+ # - in OpenSTA 3, that's whatever sta::find_scene returns (a name in
52
+ # OpenSTA 3.0, a Scene object since 3.1)
40
53
  # - in OpenSTA 2, that's an opaque Tcl pointer
41
54
  set result [dict create]
42
55
  if {[string length [namespace which sta::scenes]] != 0} {
43
56
  foreach scene [sta::scenes] {
44
- dict set result $scene $scene
57
+ set name [scene_name $scene]
58
+ dict set result $name [sta::find_scene $name]
45
59
  }
46
60
  } else {
47
61
  foreach corner [sta::corners] {
@@ -52,7 +66,11 @@ namespace eval lln {
52
66
  }
53
67
 
54
68
  proc set_sta_cmd_corner {corner_name} {
55
- if {[string length [namespace which sta::set_cmd_scene]] != 0} {
69
+ # sta::set_scene takes a name in every OpenSTA 3; sta::set_cmd_scene
70
+ # takes a name before 998806cb and a Scene object after.
71
+ if {[string length [namespace which sta::set_scene]] != 0} {
72
+ sta::set_scene $corner_name
73
+ } elseif {[string length [namespace which sta::set_cmd_scene]] != 0} {
56
74
  sta::set_cmd_scene $corner_name
57
75
  } else {
58
76
  set corner_object [sta::find_corner $corner_name]
@@ -49,11 +49,11 @@ lappend arg_list -verbose
49
49
  lappend arg_list -max_wire_length $::env(DESIGN_REPAIR_MAX_WIRE_LENGTH)
50
50
  lappend arg_list -slew_margin $::env(DESIGN_REPAIR_MAX_SLEW_PCT)
51
51
  lappend arg_list -cap_margin $::env(DESIGN_REPAIR_MAX_CAP_PCT)
52
- if { [info exists ::env(DESIGN_REPAIR_MAX_UTILIZATION)] } {
52
+ if { $::env(DESIGN_REPAIR_MAX_UTILIZATION) > 0 } {
53
53
  lappend arg_list -max_utilization $::env(DESIGN_REPAIR_MAX_UTILIZATION)
54
54
  }
55
- if { [info exists ::env(DESIGN_REPAIR_BUFFER_GAIN)] } {
56
- lappend arg_list -buffer_gain $::env(DESIGN_REPAIR_BUFFER_GAIN)
55
+ if { $::env(DESIGN_REPAIR_PRE_PLACEMENT) } {
56
+ lappend arg_list -pre_placement
57
57
  }
58
58
  # Repair Design
59
59
  log_cmd repair_design {*}$arg_list
@@ -36,12 +36,9 @@ lappend arg_list -verbose
36
36
  lappend arg_list -max_wire_length $::env(GRT_DESIGN_REPAIR_MAX_WIRE_LENGTH)
37
37
  lappend arg_list -slew_margin $::env(GRT_DESIGN_REPAIR_MAX_SLEW_PCT)
38
38
  lappend arg_list -cap_margin $::env(GRT_DESIGN_REPAIR_MAX_CAP_PCT)
39
- if { [info exists ::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION)] } {
39
+ if { $::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION) > 0 } {
40
40
  lappend arg_list -max_utilization $::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION)
41
41
  }
42
- if { [info exists ::env(GRT_DESIGN_REPAIR_BUFFER_GAIN)] } {
43
- lappend arg_list -buffer_gain $::env(GRT_DESIGN_REPAIR_BUFFER_GAIN)
44
- }
45
42
  log_cmd repair_design {*}$arg_list
46
43
 
47
44
  # Re-DPL and GRT
@@ -257,6 +257,10 @@ def synthesize(
257
257
  config = json.load(open(config_in))
258
258
  extra = json.load(open(extra_in))
259
259
 
260
+ lib_dont_use_args = []
261
+ for excluded_cell in extra["excluded_cell_patterns"]:
262
+ lib_dont_use_args.extend(("-dont_use", excluded_cell))
263
+
260
264
  includes = config.get("VERILOG_INCLUDE_DIRS") or []
261
265
  defines = (
262
266
  (config.get("VERILOG_DEFINES") or [])
@@ -288,7 +292,7 @@ def synthesize(
288
292
  # https://github.com/YosysHQ/abc/blob/28d955ca97a1c4be3aed4062aec0241a734fac5d/src/map/scl/sclUtil.c#L257
289
293
  sdc_path = os.path.join(step_dir, "synthesis.abc.sdc")
290
294
  with open(sdc_path, "w") as f:
291
- print(f"set_driving_cell {config['SYNTH_DRIVING_CELL']}", file=f)
295
+ print(f"set_driving_cell {config['SYNTH_DRIVING_CELL'].split('/')[0]}", file=f)
292
296
  print(f"set_load {config['OUTPUT_CAP_LOAD']}", file=f)
293
297
 
294
298
  ys.log(f"[INFO] Using SDC file '{sdc_path}' for ABC…")
@@ -434,6 +438,7 @@ def synthesize(
434
438
  cg_min_width = config["SYNTH_CLOCKGATE_MIN_WIDTH"]
435
439
  posedge = ()
436
440
  negedge = ()
441
+ tie_lo = ()
437
442
  if posedge_raw := config["SYNTH_CLOCKGATE_POSEDGE_ICG"]:
438
443
  cell, ce, clk, gclk = posedge_raw.rsplit("/", maxsplit=4)
439
444
  posedge = ("-pos", cell, f"{ce}:{clk}:{gclk}")
@@ -444,18 +449,21 @@ def synthesize(
444
449
  ys.log(
445
450
  "[WARNING] A minimum width for clock gating is set; but no ICGs are configured."
446
451
  )
452
+ if tie_lo_raw := config["SYNTH_CLOCKGATE_TIE_LO"]:
453
+ tie_lo = ("-tie_lo", tie_lo_raw)
447
454
  d.run_pass(
448
455
  "clockgate",
449
456
  "-min_net_size",
450
457
  str(cg_min_width),
451
458
  *posedge,
452
459
  *negedge,
460
+ *tie_lo,
453
461
  )
454
462
 
455
463
  dfflibmap_args = []
456
464
  for lib in libs:
457
465
  dfflibmap_args.extend(["-liberty", lib])
458
- d.run_pass("dfflibmap", *dfflibmap_args)
466
+ d.run_pass("dfflibmap", *dfflibmap_args, *lib_dont_use_args)
459
467
 
460
468
  d.tee("stat", "-json", *lib_arguments, o=os.path.join(report_dir, "post_dff.json"))
461
469
  d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "post_dff.rpt"))
@@ -465,24 +473,35 @@ def synthesize(
465
473
  def run_strategy(d):
466
474
  abc_script = config["SYNTH_ABC_STRATEGY_SCRIPT"]
467
475
  if abc_script:
468
- ys.log(f"[INFO] Using custom ABC strategy script '{abc_script}'…")
469
- else:
470
- abc_script = script_creator.generate_abc_script(
471
- step_dir,
472
- config["SYNTH_STRATEGY"],
473
- )
474
- ys.log(f"[INFO] Using generated ABC strategy script '{abc_script}'…")
475
-
476
- d.run_pass(
477
- "abc",
478
- "-script",
479
- abc_script,
476
+ ys.log(f"[INFO] Using custom ABC strategy script '{abc_script}'…\n")
477
+ elif config["SYNTH_STRATEGY"] != "DEFAULT":
478
+ if config["SYNTH_ABC_NEW"]:
479
+ ys.log(
480
+ "[WARN] Using Yosys-provided synthesis strategy for experimental abc_new pass: use SYNTH_ABC_STRATEGY_SCRIPT to provide your own synthesis scripts."
481
+ )
482
+ else:
483
+ abc_script = script_creator.generate_abc_script(
484
+ step_dir,
485
+ config["SYNTH_STRATEGY"],
486
+ )
487
+ ys.log(f"[INFO] Using generated ABC strategy script '{abc_script}'…\n")
488
+ ys.log_flush()
489
+
490
+ extra_args = ["-script", abc_script] * bool(abc_script)
491
+ if not config["SYNTH_ABC_NEW"]:
492
+ extra_args += ["-showtmp"]
493
+ if config["SYNTH_ABC_DFF"]:
494
+ extra_args += ["-dff"]
495
+
496
+ abc_pass = [
497
+ "abc_new" if config["SYNTH_ABC_NEW"] else "abc",
480
498
  "-constr",
481
499
  sdc_path,
482
- "-showtmp",
483
500
  *lib_arguments,
484
- *(["-dff"] if config["SYNTH_ABC_DFF"] else []),
485
- )
501
+ *extra_args,
502
+ *lib_dont_use_args,
503
+ ]
504
+ d.run_pass(*abc_pass)
486
505
 
487
506
  if value := config.get("SYNTH_TIE_UNDEFINED"):
488
507
  flag = "-zero" if value == "low" else "-one"
@@ -18,6 +18,7 @@
18
18
  import os
19
19
  import re
20
20
  import sys
21
+ import shlex
21
22
  from typing import Iterable, List, Optional, Tuple, Union
22
23
 
23
24
  try:
@@ -64,6 +65,9 @@ def yosys_version_at_least(*target: Tuple[int, ...]) -> Tuple[int, int]:
64
65
 
65
66
 
66
67
  def _Design_run_pass(self, *command):
68
+ if pass_dump := os.getenv("_LIBRELANE_YOSYS_DUMP_PASSES_TO"):
69
+ with open(pass_dump, "a+", encoding="utf8") as f:
70
+ print(shlex.join(command), file=f)
67
71
  ys.Pass.call(self, command)
68
72
 
69
73
 
@@ -151,6 +155,8 @@ def _Design_add_blackbox_models(
151
155
  "-sv",
152
156
  "-setattr",
153
157
  "keep_hierarchy",
158
+ "-setattr",
159
+ "blackbox",
154
160
  "-lib",
155
161
  *include_args,
156
162
  *define_args,
@@ -165,6 +171,7 @@ def _Design_add_blackbox_models(
165
171
  "blackbox",
166
172
  "-setattr",
167
173
  "keep_hierarchy",
174
+ "-unit_delay",
168
175
  model,
169
176
  )
170
177
  else:
@@ -459,10 +459,13 @@ class DRC(KLayoutStep):
459
459
  deprecated_names=["KLAYOUT_DRC_TECH_SCRIPT"],
460
460
  ),
461
461
  Variable(
462
- "KLAYOUT_DRC_OPTIONS",
463
- Optional[Dict[str, Union[int, bool, str]]],
462
+ "KLAYOUT_DRC_DEFINES",
463
+ Optional[Dict[str, str]],
464
464
  "Options passed directly to the KLayout DRC runset. They vary from one PDK to another.",
465
465
  pdk=True,
466
+ deprecated_names=[
467
+ ("KLAYOUT_DRC_OPTIONS", lambda x: {k: str(v) for k, v in x.items()})
468
+ ],
466
469
  ),
467
470
  Variable(
468
471
  "KLAYOUT_DRC_THREADS",
@@ -505,8 +508,8 @@ class DRC(KLayoutStep):
505
508
  assert isinstance(input_view, Path)
506
509
 
507
510
  opts = []
508
- if self.config["KLAYOUT_DRC_OPTIONS"]:
509
- for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
511
+ if self.config["KLAYOUT_DRC_DEFINES"]:
512
+ for k, v in self.config["KLAYOUT_DRC_DEFINES"].items():
510
513
  opts.extend(
511
514
  [
512
515
  "-rd",
@@ -566,13 +569,13 @@ class DRC(KLayoutStep):
566
569
  drc_script_path = self.config["KLAYOUT_DRC_RUNSET"]
567
570
  lyrdb_report = os.path.join(reports_dir, "drc.klayout.lyrdb")
568
571
  json_report = os.path.join(reports_dir, "drc.klayout.json")
569
- feol = str(self.config["KLAYOUT_DRC_OPTIONS"]["feol"]).lower()
570
- beol = str(self.config["KLAYOUT_DRC_OPTIONS"]["beol"]).lower()
572
+ feol = str(self.config["KLAYOUT_DRC_DEFINES"]["feol"]).lower()
573
+ beol = str(self.config["KLAYOUT_DRC_DEFINES"]["beol"]).lower()
571
574
  floating_metal = str(
572
- self.config["KLAYOUT_DRC_OPTIONS"]["floating_metal"]
575
+ self.config["KLAYOUT_DRC_DEFINES"]["floating_metal"]
573
576
  ).lower()
574
- offgrid = str(self.config["KLAYOUT_DRC_OPTIONS"]["offgrid"]).lower()
575
- seal = str(self.config["KLAYOUT_DRC_OPTIONS"]["seal"]).lower()
577
+ offgrid = str(self.config["KLAYOUT_DRC_DEFINES"]["offgrid"]).lower()
578
+ seal = str(self.config["KLAYOUT_DRC_DEFINES"]["seal"]).lower()
576
579
  threads = self.config["KLAYOUT_DRC_THREADS"] or _get_process_limit()
577
580
  info(f"Running KLayout DRC with {threads} threads…")
578
581
 
@@ -648,8 +651,8 @@ class DRC(KLayoutStep):
648
651
  assert isinstance(input_view, Path)
649
652
 
650
653
  opts = []
651
- if self.config["KLAYOUT_DRC_OPTIONS"]:
652
- for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
654
+ if self.config["KLAYOUT_DRC_DEFINES"]:
655
+ for k, v in self.config["KLAYOUT_DRC_DEFINES"].items():
653
656
  opts.extend(
654
657
  [
655
658
  "-rd",
@@ -717,8 +720,8 @@ class DRC(KLayoutStep):
717
720
  assert isinstance(input_view, Path)
718
721
 
719
722
  opts = []
720
- if self.config["KLAYOUT_DRC_OPTIONS"]:
721
- for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
723
+ if self.config["KLAYOUT_DRC_DEFINES"]:
724
+ for k, v in self.config["KLAYOUT_DRC_DEFINES"].items():
722
725
  opts.extend(
723
726
  [
724
727
  "-rd",
@@ -1037,10 +1040,16 @@ class Filler(KLayoutStep):
1037
1040
  pdk=True,
1038
1041
  ),
1039
1042
  Variable(
1040
- "KLAYOUT_FILLER_OPTIONS",
1041
- Optional[Dict[str, Union[bool, int, str]]],
1042
- "Options passed directly to the KLayout filler script. They vary from one PDK to another.",
1043
+ "KLAYOUT_FILLER_DEFINES",
1044
+ Optional[Dict[str, str]],
1045
+ "Options passed directly to the KLayout filler runset. They vary from one PDK to another.",
1043
1046
  pdk=True,
1047
+ deprecated_names=[
1048
+ (
1049
+ "KLAYOUT_FILLER_OPTIONS",
1050
+ lambda x: {k: str(v) for k, v in (x or {}).items()},
1051
+ )
1052
+ ],
1044
1053
  ),
1045
1054
  ]
1046
1055
 
@@ -1076,8 +1085,8 @@ class Filler(KLayoutStep):
1076
1085
  script = self.config["KLAYOUT_FILLER_SCRIPT"]
1077
1086
 
1078
1087
  opts = []
1079
- if self.config["KLAYOUT_FILLER_OPTIONS"]:
1080
- for k, v in self.config["KLAYOUT_FILLER_OPTIONS"].items():
1088
+ if self.config["KLAYOUT_FILLER_DEFINES"]:
1089
+ for k, v in self.config["KLAYOUT_FILLER_DEFINES"].items():
1081
1090
  opts.extend(
1082
1091
  [
1083
1092
  "-rd",
@@ -1119,6 +1128,16 @@ class Filler(KLayoutStep):
1119
1128
 
1120
1129
  script = self.config["KLAYOUT_FILLER_SCRIPT"]
1121
1130
 
1131
+ opts = []
1132
+ if self.config["KLAYOUT_FILLER_DEFINES"]:
1133
+ for k, v in self.config["KLAYOUT_FILLER_DEFINES"].items():
1134
+ opts.extend(
1135
+ [
1136
+ "-rd",
1137
+ f"{k}={v}",
1138
+ ]
1139
+ )
1140
+
1122
1141
  env["PDK_ROOT"] = self.config["PDK_ROOT"]
1123
1142
  env["PDK"] = self.config["PDK"]
1124
1143
 
@@ -1132,6 +1151,7 @@ class Filler(KLayoutStep):
1132
1151
  "-rd",
1133
1152
  f"output_file={abspath(output_gds)}",
1134
1153
  abspath(input_gds),
1154
+ *opts,
1135
1155
  ],
1136
1156
  env=env,
1137
1157
  )
@@ -1161,10 +1181,16 @@ class Density(KLayoutStep):
1161
1181
  pdk=True,
1162
1182
  ),
1163
1183
  Variable(
1164
- "KLAYOUT_DENSITY_OPTIONS",
1165
- Optional[Dict[str, Union[bool, int, str]]],
1184
+ "KLAYOUT_DENSITY_DEFINES",
1185
+ Optional[Dict[str, str]],
1166
1186
  "Options passed directly to the KLayout density runset. They vary from one PDK to another.",
1167
1187
  pdk=True,
1188
+ deprecated_names=[
1189
+ (
1190
+ "KLAYOUT_DENSITY_OPTIONS",
1191
+ lambda x: {k: str(v) for k, v in (x or {}).items()},
1192
+ )
1193
+ ],
1168
1194
  ),
1169
1195
  Variable(
1170
1196
  "KLAYOUT_DENSITY_THREADS",
@@ -1202,8 +1228,8 @@ class Density(KLayoutStep):
1202
1228
  json_report = os.path.join(reports_dir, "density.klayout.json")
1203
1229
 
1204
1230
  opts = []
1205
- if self.config["KLAYOUT_DENSITY_OPTIONS"]:
1206
- for k, v in self.config["KLAYOUT_DENSITY_OPTIONS"].items():
1231
+ if self.config["KLAYOUT_DENSITY_DEFINES"]:
1232
+ for k, v in self.config["KLAYOUT_DENSITY_DEFINES"].items():
1207
1233
  opts.extend(
1208
1234
  [
1209
1235
  "-rd",
@@ -1279,10 +1305,16 @@ class Antenna(KLayoutStep):
1279
1305
  pdk=True,
1280
1306
  ),
1281
1307
  Variable(
1282
- "KLAYOUT_ANTENNA_OPTIONS",
1283
- Optional[Dict[str, Union[bool, int, str]]],
1284
- "Options passed directly to the KLayout density runset. They vary from one PDK to another.",
1308
+ "KLAYOUT_ANTENNA_DEFINES",
1309
+ Optional[Dict[str, str]],
1310
+ "Options passed directly to the KLayout antenna runset. They vary from one PDK to another.",
1285
1311
  pdk=True,
1312
+ deprecated_names=[
1313
+ (
1314
+ "KLAYOUT_ANTENNA_OPTIONS",
1315
+ lambda x: {k: str(v) for k, v in (x or {}).items()},
1316
+ )
1317
+ ],
1286
1318
  ),
1287
1319
  ]
1288
1320
 
@@ -1314,8 +1346,8 @@ class Antenna(KLayoutStep):
1314
1346
  json_report = os.path.join(reports_dir, "antenna.klayout.json")
1315
1347
 
1316
1348
  opts = []
1317
- if self.config["KLAYOUT_ANTENNA_OPTIONS"]:
1318
- for k, v in self.config["KLAYOUT_ANTENNA_OPTIONS"].items():
1349
+ if self.config["KLAYOUT_ANTENNA_DEFINES"]:
1350
+ for k, v in self.config["KLAYOUT_ANTENNA_DEFINES"].items():
1319
1351
  opts.extend(
1320
1352
  [
1321
1353
  "-rd",
@@ -516,7 +516,7 @@ class OpenROADStep(TclStep):
516
516
 
517
517
  def get_command(self) -> List[str]:
518
518
  metrics_path = os.path.join(self.step_dir, "or_metrics_out.json")
519
- threads = str(self.config["OPENROAD_THREADS"]) or str(_get_process_limit())
519
+ threads = str(self.config["OPENROAD_THREADS"] or _get_process_limit())
520
520
  verbose(f"OpenROAD will use {threads} threads")
521
521
  return [
522
522
  self.get_openroad_path(),
@@ -2667,6 +2667,19 @@ class RepairDesignPostGPL(ResizerStep):
2667
2667
  "Invokes OpenROAD's remove_buffers command to remove buffers from synthesis, which gives OpenROAD more flexibility when buffering nets.",
2668
2668
  default=False,
2669
2669
  ),
2670
+ Variable(
2671
+ "DESIGN_REPAIR_MAX_UTILIZATION",
2672
+ Decimal,
2673
+ "Defines the percentage of core area used.",
2674
+ units="%",
2675
+ default=0,
2676
+ ),
2677
+ Variable(
2678
+ "DESIGN_REPAIR_PRE_PLACEMENT",
2679
+ bool,
2680
+ "Enables performing an initial pre-placement sizing and buffering round.",
2681
+ default=False,
2682
+ ),
2670
2683
  ]
2671
2684
 
2672
2685
  def get_script_path(self):
@@ -2723,6 +2736,13 @@ class RepairDesignPostGRT(ResizerStep):
2723
2736
  units="%",
2724
2737
  deprecated_names=["GLB_RESIZER_MAX_CAP_MARGIN"],
2725
2738
  ),
2739
+ Variable(
2740
+ "GRT_DESIGN_REPAIR_MAX_UTILIZATION",
2741
+ Decimal,
2742
+ "Defines the percentage of core area used during post-grt repair.",
2743
+ units="%",
2744
+ default=0,
2745
+ ),
2726
2746
  ]
2727
2747
 
2728
2748
  def get_script_path(self):
librelane/steps/pyosys.py CHANGED
@@ -214,6 +214,12 @@ class PyosysStep(Step):
214
214
  pdk=True,
215
215
  validator=_validate_icg,
216
216
  ),
217
+ Variable(
218
+ "SYNTH_CLOCKGATE_TIE_LO",
219
+ Optional[str],
220
+ "Port of the integrated clock gate cell to be tied to zero. Intended for DFT scan-enable pins.",
221
+ pdk=True,
222
+ ),
217
223
  Variable(
218
224
  "YOSYS_LOG_LEVEL",
219
225
  Literal["ALL", "WARNING", "ERROR"],
@@ -268,7 +274,7 @@ class PyosysStep(Step):
268
274
  env["PYTHONPATH"] = ":".join(
269
275
  (env.get("PYTHONPATH", ""), os.path.join(get_script_dir(), "pyosys"))
270
276
  )
271
- subprocess_result = super().run_subprocess(cmd, env=env, **kwargs)
277
+ subprocess_result = self.run_subprocess(cmd, env=env, **kwargs)
272
278
  return {}, subprocess_result["generated_metrics"]
273
279
 
274
280
 
@@ -287,6 +293,11 @@ class VerilogStep(PyosysStep):
287
293
  pad_lib_list = self.toolbox.filter_views(
288
294
  self.config, self.config["PAD_LIBS"], self.config.get("SYNTH_CORNER")
289
295
  )
296
+ pad_lib_list = []
297
+ if pad_libs := self.config.get("PAD_LIBS"):
298
+ pad_lib_list = self.toolbox.filter_views(
299
+ self.config, pad_libs, self.config.get("SYNTH_CORNER")
300
+ )
290
301
 
291
302
  # Try your best to use powered blackbox models if power_defines is true
292
303
  if self.power_defines:
@@ -338,19 +349,27 @@ class VerilogStep(PyosysStep):
338
349
  if models := self.config.get("EXTRA_VERILOG_MODELS"):
339
350
  blackbox_models.extend(str(f) for f in models)
340
351
 
341
- excluded_cells: Set[str] = set(self.config["EXTRA_EXCLUDED_CELLS"] or [])
342
- excluded_cells.update(
352
+ excluded_cell_patterns: Set[str] = set(
353
+ self.config["EXTRA_EXCLUDED_CELLS"] or []
354
+ )
355
+ excluded_cell_patterns.update(
343
356
  process_list_file(self.config["SYNTH_EXCLUDED_CELL_FILE"])
344
357
  )
345
- excluded_cells.update(process_list_file(self.config["PNR_EXCLUDED_CELL_FILE"]))
346
-
347
- libs_synth = self.toolbox.remove_cells_from_lib(
348
- frozenset([str(lib) for lib in scl_lib_list + pad_lib_list]),
349
- excluded_cells=frozenset(excluded_cells),
358
+ excluded_cell_patterns.update(
359
+ process_list_file(self.config["PNR_EXCLUDED_CELL_FILE"])
350
360
  )
361
+
362
+ libs_synth = [str(p) for p in scl_lib_list + pad_lib_list]
351
363
  extra_path = os.path.join(self.step_dir, "extra.json")
352
364
  with open(extra_path, "w") as f:
353
- json.dump({"blackbox_models": blackbox_models, "libs_synth": libs_synth}, f)
365
+ json.dump(
366
+ {
367
+ "blackbox_models": blackbox_models,
368
+ "libs_synth": libs_synth,
369
+ "excluded_cell_patterns": list(excluded_cell_patterns),
370
+ },
371
+ f,
372
+ )
354
373
  cmd.extend(["--extra-in", extra_path])
355
374
  return cmd
356
375
 
@@ -411,9 +430,27 @@ class SynthesisCommon(VerilogStep):
411
430
  "Generates names for netlist instances. This results in instance names that can be extremely long, but are more human-readable.",
412
431
  default=False,
413
432
  ),
433
+ Variable(
434
+ "SYNTH_ABC_NEW",
435
+ bool,
436
+ "Experimental: Use the abc_new pass instead of abc, with the default synthesis strategy from Yosys.",
437
+ default=False,
438
+ ),
439
+ Variable(
440
+ "SYNTH_ABC_DFF",
441
+ bool,
442
+ "Passes D-flipflop cells through ABC for optimization (which can for example, eliminate identical flip-flops). Has no effect if SYNTH_ABC_NEW is true.",
443
+ default=False,
444
+ ),
445
+ Variable(
446
+ "SYNTH_ABC_STRATEGY_SCRIPT",
447
+ Optional[Path],
448
+ "Custom ABC strategy script, overriding the script generated by the SYNTH_STRATEGY.",
449
+ ),
414
450
  Variable(
415
451
  "SYNTH_STRATEGY",
416
452
  Literal[
453
+ "DEFAULT",
417
454
  "AREA 0",
418
455
  "AREA 1",
419
456
  "AREA 2",
@@ -424,51 +461,40 @@ class SynthesisCommon(VerilogStep):
424
461
  "DELAY 3",
425
462
  "DELAY 4",
426
463
  ],
427
- "Strategies for abc logic synthesis and technology mapping. AREA strategies usually result in a more compact design, while DELAY strategies usually result in a design that runs at a higher frequency. Please note that there is no way to know which strategy is the best before trying them.",
428
- default="AREA 0",
464
+ "Strategies for abc logic synthesis and technology mapping. DEFAULT uses whichever script Yosys applies by default. AREA strategies usually result in a more compact design, while DELAY strategies usually result in a design that runs at a higher frequency. Please note that there is no way to know which strategy is the best before trying them. Has no effect if SYNTH_ABC_STRATEGY_SCRIPT is set. While marked experimental, SYNTH_ABC_NEW will always use DEFAULT.",
465
+ default="DELAY 4",
429
466
  ),
430
467
  Variable(
431
468
  "SYNTH_ABC_BUFFERING",
432
469
  bool,
433
- "Enables `abc` cell buffering.",
470
+ "Enables `abc` cell buffering. Has no effect if either SYNTH_ABC_NEW is true or SYNTH_ABC_STRATEGY_SCRIPT is set.",
434
471
  default=False,
435
472
  deprecated_names=["SYNTH_BUFFERING"],
436
473
  ),
437
474
  Variable(
438
475
  "SYNTH_ABC_LEGACY_REFACTOR",
439
476
  bool,
440
- "Replaces the ABC command `drf -l` with `refactor` which matches older versions of LibreLane but is more unstable.",
477
+ "Replaces the ABC command `drf -l` with `refactor` which matches older versions of LibreLane but is more unstable. Has no effect if either SYNTH_ABC_NEW is true or SYNTH_ABC_STRATEGY_SCRIPT is set.",
441
478
  default=False,
442
479
  ),
443
480
  Variable(
444
481
  "SYNTH_ABC_LEGACY_REWRITE",
445
482
  bool,
446
- "Replaces the ABC command `drw -l` with `rewrite` which matches older versions of LibreLane but is more unstable.",
447
- default=False,
448
- ),
449
- Variable(
450
- "SYNTH_ABC_DFF",
451
- bool,
452
- "Passes D-flipflop cells through ABC for optimization (which can for example, eliminate identical flip-flops).",
483
+ "Replaces the ABC command `drw -l` with `rewrite` which matches older versions of LibreLane but is more unstable. Has no effect if either SYNTH_ABC_NEW is true or SYNTH_ABC_STRATEGY_SCRIPT is set.",
453
484
  default=False,
454
485
  ),
455
486
  Variable(
456
487
  "SYNTH_ABC_USE_MFS3",
457
488
  bool,
458
- "Experimental: attempts a SAT-based remapping in all area and delay strategies before 'retime', which may improve PPA results.",
489
+ "Experimental: attempts a SAT-based remapping in all area and delay strategies before 'retime', which may improve PPA results. Has no effect if either SYNTH_ABC_NEW is true or SYNTH_ABC_STRATEGY_SCRIPT is set.",
459
490
  default=False,
460
491
  ),
461
492
  Variable(
462
493
  "SYNTH_ABC_AREA_USE_NF",
463
494
  bool,
464
- "Experimental: uses the &nf delay-based mapper with a very high value instead of the amap area mapper, which may be better in some scenarios at recovering area.",
495
+ "Experimental: uses the &nf delay-based mapper with a very high value instead of the amap area mapper, which may be better in some scenarios at recovering area. Has no effect if either SYNTH_ABC_NEW is true or SYNTH_ABC_STRATEGY_SCRIPT is set.",
465
496
  default=False,
466
497
  ),
467
- Variable(
468
- "SYNTH_ABC_STRATEGY_SCRIPT",
469
- Optional[Path],
470
- "Custom ABC strategy script. Runs instead of the default script for the selected 'SYNTH_STRATEGY'. All other 'SYNTH_ABC_*' variables except 'SYNTH_ABC_DFF' will have no effect.",
471
- ),
472
498
  Variable(
473
499
  "SYNTH_DIRECT_WIRE_BUFFERING",
474
500
  bool,
@@ -610,17 +636,19 @@ class SynthesisCommon(VerilogStep):
610
636
  ]
611
637
  metric_updates["design__instance_unmapped__count"] = sum(unmapped_cells)
612
638
 
613
- check_error_count_file = os.path.join(
614
- self.step_dir, "reports", "pre_synth_chk.rpt"
615
- )
639
+ check_report_files = [
640
+ os.path.join(self.step_dir, "reports", "pre_synth_chk.rpt"),
641
+ os.path.join(self.step_dir, "reports", "chk.rpt"),
642
+ ]
616
643
  metric_updates["synthesis__check_error__count"] = 0
617
- if os.path.exists(check_error_count_file):
618
- metric_updates["synthesis__check_error__count"] = _parse_yosys_check(
619
- open(check_error_count_file),
620
- self.config["TRISTATE_CELLS"],
621
- self.config["SYNTH_CHECKS_ALLOW_TRISTATE"],
622
- self.config["SYNTH_ELABORATE_ONLY"],
623
- )
644
+ for check_error_count_file in check_report_files:
645
+ if os.path.exists(check_error_count_file):
646
+ metric_updates["synthesis__check_error__count"] += _parse_yosys_check(
647
+ open(check_error_count_file),
648
+ self.config["TRISTATE_CELLS"],
649
+ self.config["SYNTH_CHECKS_ALLOW_TRISTATE"],
650
+ self.config["SYNTH_ELABORATE_ONLY"],
651
+ )
624
652
 
625
653
  view_updates[DesignFormat.NETLIST] = Path(out_file)
626
654
 
librelane/steps/step.py CHANGED
@@ -313,7 +313,7 @@ class ProcessStatsThread(Thread):
313
313
  time.sleep(self.interval)
314
314
  status = self.process.status()
315
315
  except psutil.Error as e:
316
- message = e.msg
316
+ message = str(e)
317
317
  for normal in ["process no longer exists", "but it's a zombie"]:
318
318
  if normal in message:
319
319
  return
@@ -165,7 +165,7 @@ class Lint(Step):
165
165
  model_set.add(str_model)
166
166
  model_list.append(str_model)
167
167
  defines = [
168
- f"PDK_{self.config['PDK']}",
168
+ f"PDK_{self.config['PDK']}.replace('-','_')",
169
169
  f"SCL_{self.config['STD_CELL_LIBRARY']}",
170
170
  "__librelane__",
171
171
  "__pnr__",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: librelane
3
- Version: 3.1.0.dev3
3
+ Version: 3.1.0.dev4
4
4
  Summary: An infrastructure for implementing chip design flows
5
5
  License-Expression: Apache-2.0
6
6
  Maintainer: Mohamed Gaber
@@ -12,7 +12,8 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Classifier: Programming Language :: Python :: 3.14
15
- Requires-Dist: ciel (>=2.3.1,<3)
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Requires-Dist: ciel (>=3.2.0,<4)
16
17
  Requires-Dist: click (>=8,<8.4)
17
18
  Requires-Dist: cloup (>=3.0.5,<4)
18
19
  Requires-Dist: deprecated (>=1.2.10,<2)
@@ -1,7 +1,7 @@
1
1
  librelane/__init__.py,sha256=Xbz6e-J9pNxv0AIi89-mApMEQQtRgxJyzHS6yYc00Y0,1221
2
2
  librelane/__main__.py,sha256=QLV5xjX9p_xXltrb9JgXkvG9gC6G3oxMfM6vOvrY138,14904
3
3
  librelane/__version__.py,sha256=TRnK0R8jG4P_eiX1VVShHpLWZljMLwhDggTIYW1lBSk,1598
4
- librelane/common/__init__.py,sha256=fK52kxuueEpKI1HNNhUOJFQ4yvxJs0f0Vz1a5S-CBGY,1569
4
+ librelane/common/__init__.py,sha256=wrVBpwXBQTVRy7COwWulyTHwnV2Rx5nh2gWNMVEf06w,1592
5
5
  librelane/common/cli.py,sha256=XeNFI1B-lM-luGJfCVa88wUl9Q5S4btEwzXTAui1xYU,2413
6
6
  librelane/common/drc.py,sha256=ujwGdwQoq8aXBwpJNn2r-o808iUfj8IJx2SglBzw5YU,12853
7
7
  librelane/common/generic_dict.py,sha256=ASa5wtVcLuGlsBqGfLxLYXrYksqQB62iHljV04plIqI,10010
@@ -11,20 +11,20 @@ librelane/common/metrics/compare.py,sha256=dPJmtcDKQpMUEqQBx4eynJddCNxAA0_zwvJ0u
11
11
  librelane/common/metrics/library.py,sha256=CG7rubLdjuCQL9-9bzAC-64hf-KlH-iu_Fg0oKuesqs,7373
12
12
  librelane/common/metrics/metric.py,sha256=h3Xd26z5M80IJgVmmrBTjKcdGLb4I0wyjM-H4jdyi_0,6990
13
13
  librelane/common/metrics/util.py,sha256=Bl_9znlot7-Os2VigYLSmMf56aAkGdv3evWz9vfK7K4,9344
14
- librelane/common/misc.py,sha256=Jry0rW7VzCgrmHGmX4F6hKvNefa9rmWj8_ZMxnrlpQE,14836
14
+ librelane/common/misc.py,sha256=lMJcMt0Vp8jXrqzQxsglz5tLKjPjodMHUr7r76Amas0,15584
15
15
  librelane/common/ring_buffer.py,sha256=DGFen9y0JOmiL7E27tmzDTVSJKZtV-waF9hl5Rz9uek,1898
16
16
  librelane/common/tcl.py,sha256=kq09m9dj-RK7uvvduAgxHMCf0xjzMRS9IPcrhQFl-Xc,4350
17
- librelane/common/toolbox.py,sha256=VPjZ_8D2oUiubwZw112F8J-gUbsnBSGlxQeZlCf5fRM,21211
17
+ librelane/common/toolbox.py,sha256=-fIOD9yjLEB4KFF30e7r3iPRfAmJMjL5Yx_hY5YSI7o,21383
18
18
  librelane/common/tpe.py,sha256=Txj0fVscXSDJTYmEKZ2ESFHOeqrhHnaPPiwWBgyx4g8,1285
19
19
  librelane/common/types.py,sha256=yFzUWnfnwrzhOz06uh45oHY8un0kDk4CJR5B32TbQDw,3950
20
- librelane/config/__init__.py,sha256=lbJmD5CbrrrnaNdIUWqFIK488ea0uyej3iExh-9mkgE,1107
21
- librelane/config/__main__.py,sha256=NsJGoIOb950mdXql1zmzSq10wuFovK9NGWm011NNJ3A,4474
22
- librelane/config/config.py,sha256=pAT6LqTiCVQykUQiJXYSmBimHDWcbha9IF-XTJ48f58,36928
23
- librelane/config/flow.py,sha256=mBZkBuQOvke9Xf8OQuTvGmJSX72UfQ5xI0ycTbNm-dc,18618
24
- librelane/config/pdk_compat.py,sha256=35tgW_vrn5kxPVUaA8vlnJ77mkHKvJlvYiYUrjV4k9s,13992
25
- librelane/config/preprocessor.py,sha256=0SNRaPTAwABi3vkvCzcchqTqkuTGjFOIVZRiQHdAFkU,14521
26
- librelane/config/removals.py,sha256=57jRLJ8505IsNbyr68iAyHBFEyIloq7DQUPw4L3iisc,3173
27
- librelane/config/variable.py,sha256=yfnco9zux0dZ74wp0-ObZyUEnwIdEHIOVCuJHj-9noc,35322
20
+ librelane/config/__init__.py,sha256=xDSlMiZsjAwdfsGErJPjsY2pfa5vbazRiNcKNJ2udf8,1177
21
+ librelane/config/__main__.py,sha256=iGva_Hv3zQ4OnV-Y9POgcDl1Fkz4RYZcfa2G9zroLuk,4544
22
+ librelane/config/config.py,sha256=v_NWe6BVKvMAEiSaWklILsiL1QOyz60R8du-4X9Kj2A,37003
23
+ librelane/config/flow.py,sha256=9uV_KWu8jigcmN8YHEJokJIHxAvbz-y0uFlR6ACo_Fw,18620
24
+ librelane/config/pdk_compat.py,sha256=qCj6TXiTssHRbzjKB6faqnpUytctSDrqBpdGc2Ue8qg,14789
25
+ librelane/config/preprocessor.py,sha256=n3IrZUWxgodkl54B43XggT_lChItRPEmTKkNZeOGSfs,14591
26
+ librelane/config/removals.py,sha256=Fjf0GHxJGVMUKyKg-oH083OEqKjl3A3O06nMi8n9nt8,3243
27
+ librelane/config/variable.py,sha256=hN-cBCArBkIRYAvp-AawO7HlsddU4hQX9gSLkoPfKfk,35392
28
28
  librelane/container.py,sha256=GN1lqVguuqPAuTxINii-bWKBKmIQ-VJc0WHPDEp73sU,8829
29
29
  librelane/env_info.py,sha256=xF9iqwwJv5yZz7n7BTrrT_yP3Dp1HjAOUObNE9k_1g4,11074
30
30
  librelane/examples/hold_eco_demo/config.yaml,sha256=InDj4pS6o6TpyvQZyR3qCrYcIHdmCd6l04wqanKnK_A,490
@@ -46,16 +46,16 @@ librelane/flows/__init__.py,sha256=ghtmUG-taVpHJ3CKJRYZGn3dU0r93araT1EIGlBEsxg,8
46
46
  librelane/flows/builtins.py,sha256=4UbeOySaHSO8KTaTV0d__bl4ugjPtOe0NpSosdLYj_E,796
47
47
  librelane/flows/chip.py,sha256=fxmScni4ErJRSlhRy4Wyr-HaOdyjEfOn2BxBVQmkhmk,1795
48
48
  librelane/flows/classic.py,sha256=24hwOEk7CzPe-PYxdUjHpH7ykspvzc-0P19FmKmiyu0,10995
49
- librelane/flows/cli.py,sha256=k1EchdOx8G4UW0bscb8dSeQDnAfNvV4yGV66cdlOOJQ,20559
49
+ librelane/flows/cli.py,sha256=osgT-XD02HxNoO_LjorA0sIyZPY2W-aFdVAMyMKkc18,20668
50
50
  librelane/flows/flow.py,sha256=_zZfS3LvYG0GdzBJftWY-7-EPIHxeh_UnEaNAaC3ucQ,36911
51
51
  librelane/flows/misc.py,sha256=32Om3isexesfKKiJZCajNmINc-xdv7eVx_tgoh9SR6U,2015
52
52
  librelane/flows/optimizing.py,sha256=OwZz6WGmXpliwO8vtmhjKHD-kzDyNv-zoCECZIigXsI,6076
53
53
  librelane/flows/sequential.py,sha256=C5TIlWxlJh0oZ-6iCbA7Uq7-iqJkvNy6-LBPQb0TigY,15361
54
- librelane/flows/synth_explore.py,sha256=brLxVFg1VOczN_U8DqYtYkRZWFdUHqZKYjX3mf_t_es,8629
54
+ librelane/flows/synth_explore.py,sha256=MIIIX-bFpCoe1p9pi9aB4kz8Gxpmh81qMKGRDeSp6M8,8652
55
55
  librelane/help/__main__.py,sha256=gnm0yi-Ih8YoyY2cMiHONV2ZzR-tvHfdEHCb28YQJZ0,1243
56
56
  librelane/logging/__init__.py,sha256=mrTnzjpH6AOu2CiDZYfOMCVByAS2Xeg9HS4FJyXsJOE,1043
57
57
  librelane/logging/logger.py,sha256=kA61TGsR00Fi6kQSxgTC1pHpS_-zqC1PdQnYqnk2TWY,8632
58
- librelane/pdk_hashes.yaml,sha256=Q1IGbbc3VvPLwZ5IKBDtaqsC3hRLC_-gKudB0f59ii4,153
58
+ librelane/pdk_hashes.yaml,sha256=iS3gQ7RxEHTmT7mf9bteHkBXGqI5Kh7qyE_PaQnN8ZE,203
59
59
  librelane/plugins.py,sha256=G5o2h1LT4a1LO1Q0gKXXuhqcEdjdTFkYU8QUSg2D2eM,820
60
60
  librelane/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
61
  librelane/scripts/base.sdc,sha256=NMjzMcNm21Gnjtig0qe7rDtsHP4Cd6BMasqbpJSOf3g,3149
@@ -87,9 +87,9 @@ librelane/scripts/magic/wrapper.tcl,sha256=qO33N2AiEYBTABMB5vWMWWEd2FpyOhg8JlcGs
87
87
  librelane/scripts/netgen/setup.tcl,sha256=_NfZUGFeSxFzanm32r0ytipSYg6JXVjC3oPdIgYj7NY,1281
88
88
  librelane/scripts/odbpy/apply_def_template.py,sha256=Tn6y65biu0bAQ6XilYxq5jn3a_KqjTl423-aXWI864k,1534
89
89
  librelane/scripts/odbpy/cell_frequency.py,sha256=NfGgM8wxIvjM1C_GHUghZPOh8gpdasLOWR4qBdHHLFE,3105
90
- librelane/scripts/odbpy/check_antenna_properties.py,sha256=D8Hb1nzNurOzNekCZ2n2x1D-ycGTjSe9leI7qcZZHXY,3942
90
+ librelane/scripts/odbpy/check_antenna_properties.py,sha256=qDoR-f_9SNwwhZgAFVYcm45zf_UALxUocdkT3Dv2n6o,3938
91
91
  librelane/scripts/odbpy/contextualize.py,sha256=G8EEgmK6ISikXD2-Pw-RTs1JxLWPnuppwL7oPfAsb84,4020
92
- librelane/scripts/odbpy/defutil.py,sha256=gBANy_XTeLeXRBMGdCy2vI5y44qMB6E_Fy0VeyW6rUg,18104
92
+ librelane/scripts/odbpy/defutil.py,sha256=YzxP_0ePGLAVGxUvszTmfP1tArRuMx8K447emOU1lrQ,18252
93
93
  librelane/scripts/odbpy/diodes.py,sha256=qpsTW2RQlqNm4pzrUFm7d0Jj4x4zSQqladcv5SJF7XI,11752
94
94
  librelane/scripts/odbpy/disconnected_pins.py,sha256=hS_Iletg7N6K6yN_ccvWxZ3nWNZp4ecUJM-oY0kkEfA,11139
95
95
  librelane/scripts/odbpy/eco_buffer.py,sha256=lb7KtVZUzXSkPq9mRTXPVnSo_isy4845wohLFPhDN30,6292
@@ -113,7 +113,7 @@ librelane/scripts/openroad/buffer_list.tcl,sha256=sXygy1KRSUS4dZi1UOpBkGGOuXRVLM
113
113
  librelane/scripts/openroad/common/dpl.tcl,sha256=T_rzoZy8i7S9C92TOmiN79w0MCfudafEhkXcHmB1BAM,920
114
114
  librelane/scripts/openroad/common/dpl_cell_pad.tcl,sha256=KWVuj8u1-y3ZUiQr48TAsFv1GSzOCVnAjdqfBjtoQxQ,1066
115
115
  librelane/scripts/openroad/common/grt.tcl,sha256=VbZORyX7DljoylaUXyhY5vDIjAoYMlLGgrY_ZnXiJoE,1111
116
- librelane/scripts/openroad/common/io.tcl,sha256=x7KDIvCFPHxuvmB2pFTAuvPZfMYZTAkx6ue_F6RCuA8,25369
116
+ librelane/scripts/openroad/common/io.tcl,sha256=twqHM6KiagkJviINgyDXjiKhPLQYqGLB7winDaKYX-Q,26208
117
117
  librelane/scripts/openroad/common/pad_cfg.tcl,sha256=2WMNEwWJUZq3UQsTVJBDJfZE5dDdVKkYQ6b-_3iDO5g,10643
118
118
  librelane/scripts/openroad/common/pdn_cfg.tcl,sha256=ovCfiwTD-ft6OXksI9hwgZZ6ynwQohC79HIU88fHvf4,6354
119
119
  librelane/scripts/openroad/common/resizer.tcl,sha256=OhjpVxw_8IOx5Bmh2_gh_EIHxKaX84NS37Of9Rlchpw,2255
@@ -138,8 +138,8 @@ librelane/scripts/openroad/irdrop.tcl,sha256=bXhNY_87xPV-ocF9v8wOWqjlnFPaVO_6K_D
138
138
  librelane/scripts/openroad/pad.tcl,sha256=ZEFhUfGDfWm-eNp-HkB_Q82jkdPNsK8vTN4QKzlxIaI,801
139
139
  librelane/scripts/openroad/pdn.tcl,sha256=WiKVmLw3g_ZN1Hs4iiAzc6Qah7ZwCn6o-OA5iNmlTtY,1566
140
140
  librelane/scripts/openroad/rcx.tcl,sha256=kyEhli4sGFMEj-He9UXZDGb0Tmxlw7d6iZD7t6adUx8,1057
141
- librelane/scripts/openroad/repair_design.tcl,sha256=ojwbIgUHShUFEzQtTfv6gq365ExPgpXbRSuMOK9xKm0,2575
142
- librelane/scripts/openroad/repair_design_postgrt.tcl,sha256=sEXdFfH2le-q0ggcsWGgCR-GCFyzPdxk4P3RZyWCnpI,1902
141
+ librelane/scripts/openroad/repair_design.tcl,sha256=wG1owFuh5iriSUR7hd8ehCHOoq4i5DeFpOfQlsjhco8,2523
142
+ librelane/scripts/openroad/repair_design_postgrt.tcl,sha256=utJS58-WRWZN5j4mNXjzJJv5UzqFpSAwT7wdbBulN5k,1759
143
143
  librelane/scripts/openroad/rsz_timing_postcts.tcl,sha256=ztDJ__R7f3eK7-xAg9SklGXqL5F1jydGPQDH7X5twNE,2553
144
144
  librelane/scripts/openroad/rsz_timing_postgrt.tcl,sha256=F6ex9Ke85YzS4z9rf8SpqCKjMyzuiQEhYYSJfkN93sM,2699
145
145
  librelane/scripts/openroad/sta/check_macro_instances.tcl,sha256=YpHleMNIWHqQLLEl1HZlimphxyMRqUT4l09XBIeH14M,1783
@@ -150,8 +150,8 @@ librelane/scripts/openroad/write_cdl.tcl,sha256=pp-l-7JkuwpdtR1bypIVI_PKCOGCoUOD
150
150
  librelane/scripts/openroad/write_views.tcl,sha256=-MxTJsB4EF7l5trDaZe-VBFjhfzqRt8F5_DZrADTs0U,892
151
151
  librelane/scripts/pyosys/construct_abc_script.py,sha256=x_of9UOxxme-lFWlnZ75-W6I-UAWm-wJy8odnQ1alPE,6830
152
152
  librelane/scripts/pyosys/json_header.py,sha256=LSoDHLMKch3tUwsjrps2HdF6PJZ3ydxM8NZHf3z0Bz4,2525
153
- librelane/scripts/pyosys/synthesize.py,sha256=DvlKpYu1_xvv6Q1AVhyCEL82CzxZI65eGERxwjqFEow,19226
154
- librelane/scripts/pyosys/ys_common.py,sha256=My9m1mtHfgbEjeMqvOARplgYsTJQBoQMEf7gLAD0Nf8,5221
153
+ librelane/scripts/pyosys/synthesize.py,sha256=86n8dWQiAs9gIH-jGb0ow38skmZ-FSe0-dnU-S1vCkU,20130
154
+ librelane/scripts/pyosys/ys_common.py,sha256=lhyA8k1DCM59RTvRkyFxxt1oBP19sp2vl_WCL8GpCSs,5492
155
155
  librelane/scripts/tclsh/hello.tcl,sha256=kkR3akY7QnGHYXsQODYwLkMkUEOgWcNFtzaMTTEV2bY,34
156
156
  librelane/state/__init__.py,sha256=DZ_RyKMr2oj4p5d32u8MmDKfCxR7OEdDw-1HWKTpatA,949
157
157
  librelane/state/__main__.py,sha256=Ici4Ejg1ICUZNSYZRguC3BfEk_wFxsmE0ag0Vv8iY1I,1679
@@ -161,19 +161,19 @@ librelane/steps/__init__.py,sha256=j3JYrdnWM74dYuEvE931oSrQI7FUz-hKWr8Mts8C0wg,1
161
161
  librelane/steps/__main__.py,sha256=7TaEmJGiphnIqEbAALyThNQPNlelXeJRHg114P6DZ4M,13463
162
162
  librelane/steps/checker.py,sha256=CxGshm_2K1-zFTso-aPZNFuu-Y9hdSv5KkjumN6pbLY,22655
163
163
  librelane/steps/common_variables.py,sha256=tTEVB9bnZ8AnufEVZUGS6fnpQWfpyyBVK_Eax5DVD64,14990
164
- librelane/steps/klayout.py,sha256=aHfKqd66pLPCUV5WXbsDtBYXQz_kGFuBW2oH7VMgwrc,45863
164
+ librelane/steps/klayout.py,sha256=lVZwzGYWDpzoJMOAlKy8yHGV5BltXW1jz9FhfK5rrpo,46848
165
165
  librelane/steps/magic.py,sha256=GS2TzOzf3XZuYIzz5P3CQ3T_QHb47YTMaTbA9-ggb0M,28044
166
166
  librelane/steps/misc.py,sha256=3O-6V3QPnqsYACoogg9I7SrJ7C0VMQbtA0anF13wa7w,5806
167
167
  librelane/steps/netgen.py,sha256=tfHaY2ItpmmbKhSuduPvGmMw8Rqb7O1sLpXEDKSVEXg,9454
168
168
  librelane/steps/odb.py,sha256=Nrk37F33-qKz-pcCYAWvWkOlSHiLMwSqpeYldx33v1Q,40772
169
- librelane/steps/openroad.py,sha256=50p9YWgOTscAoa5rnKLGFIuX0_jG1nDbSxLFfsZbBNs,111028
169
+ librelane/steps/openroad.py,sha256=EIhmk6y_OwLwq2piJW09ZOLnsNSXeavMRaUrVxjICu8,111650
170
170
  librelane/steps/openroad_alerts.py,sha256=IJyB4piBDCKXhkJswHGMYCRDwbdQsR0GZlrGGDhmW6Q,3364
171
- librelane/steps/pyosys.py,sha256=ktRxe8PgenS-kmxsgxaCZr9tCIxL3CB5m412K0cJGkw,26328
172
- librelane/steps/step.py,sha256=gtr8xlNv4J4m4maqO6V1R0YPK_IpX6g_6X6Mk-_Oklc,55539
171
+ librelane/steps/pyosys.py,sha256=Omx4XBPol-MrINw2u4Qwl14t1uV5rXQOoHOpgAMuOcY,27819
172
+ librelane/steps/step.py,sha256=FCVcFiFQyHqjoQC3QA3Yc_x4MeDfj2k--caAxQJi4OI,55540
173
173
  librelane/steps/tclstep.py,sha256=nBCzsu9NWQ4kjOfrX5E5va1vOo8UI8nimxSY6F_Rvq4,10188
174
- librelane/steps/verilator.py,sha256=6W7ljzi8OD7NuX_v12aI9EIwQd_YJ2BXcjWu0aDO-uI,9896
174
+ librelane/steps/verilator.py,sha256=h5v5l7etVitFLReI3QSgD_Z57ZmB5Mv6Sszv5Lzz7IE,9913
175
175
  librelane/steps/yosys.py,sha256=BM1R_-omt1bSZa7J_REsbDPyW4MKv5A-ZfFzCzWu4QI,12762
176
- librelane-3.1.0.dev3.dist-info/METADATA,sha256=EWufq71fAjmL3kDEY9nIeYDsDE8eMYaMnSyolgUyKb8,8766
177
- librelane-3.1.0.dev3.dist-info/WHEEL,sha256=EGEvSphFYqXKs23-kQBeyNoJP1nrT8ZJKQoi5p5DYL8,88
178
- librelane-3.1.0.dev3.dist-info/entry_points.txt,sha256=Ub2wE2U4uZPjJgBVTPYFeXtwhNyqAqaKT8q4jGoKIUk,274
179
- librelane-3.1.0.dev3.dist-info/RECORD,,
176
+ librelane-3.1.0.dev4.dist-info/METADATA,sha256=FoDlgmk5xX6eI0YQuykcfYhi5PkiIM8SPLo9_tZsZg0,8817
177
+ librelane-3.1.0.dev4.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
178
+ librelane-3.1.0.dev4.dist-info/entry_points.txt,sha256=Ub2wE2U4uZPjJgBVTPYFeXtwhNyqAqaKT8q4jGoKIUk,274
179
+ librelane-3.1.0.dev4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.4.0
2
+ Generator: poetry-core 2.5.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any