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.
- librelane/common/__init__.py +1 -0
- librelane/common/misc.py +27 -0
- librelane/common/toolbox.py +5 -0
- librelane/config/__init__.py +4 -0
- librelane/config/__main__.py +4 -0
- librelane/config/config.py +5 -1
- librelane/config/flow.py +1 -1
- librelane/config/pdk_compat.py +20 -0
- librelane/config/preprocessor.py +4 -0
- librelane/config/removals.py +4 -0
- librelane/config/variable.py +4 -0
- librelane/flows/cli.py +20 -18
- librelane/flows/synth_explore.py +1 -0
- librelane/pdk_hashes.yaml +4 -3
- librelane/scripts/odbpy/check_antenna_properties.py +1 -1
- librelane/scripts/odbpy/defutil.py +4 -1
- librelane/scripts/openroad/common/io.tcl +23 -5
- librelane/scripts/openroad/repair_design.tcl +3 -3
- librelane/scripts/openroad/repair_design_postgrt.tcl +1 -4
- librelane/scripts/pyosys/synthesize.py +36 -17
- librelane/scripts/pyosys/ys_common.py +7 -0
- librelane/steps/klayout.py +59 -27
- librelane/steps/openroad.py +21 -1
- librelane/steps/pyosys.py +65 -37
- librelane/steps/step.py +1 -1
- librelane/steps/verilator.py +1 -1
- {librelane-3.1.0.dev3.dist-info → librelane-3.1.0.dev4.dist-info}/METADATA +3 -2
- {librelane-3.1.0.dev3.dist-info → librelane-3.1.0.dev4.dist-info}/RECORD +30 -30
- {librelane-3.1.0.dev3.dist-info → librelane-3.1.0.dev4.dist-info}/WHEEL +1 -1
- {librelane-3.1.0.dev3.dist-info → librelane-3.1.0.dev4.dist-info}/entry_points.txt +0 -0
librelane/common/__init__.py
CHANGED
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.
|
librelane/common/toolbox.py
CHANGED
|
@@ -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],
|
librelane/config/__init__.py
CHANGED
librelane/config/__main__.py
CHANGED
librelane/config/config.py
CHANGED
|
@@ -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
librelane/config/pdk_compat.py
CHANGED
|
@@ -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
|
librelane/config/preprocessor.py
CHANGED
librelane/config/removals.py
CHANGED
librelane/config/variable.py
CHANGED
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,
|
|
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
|
-
|
|
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
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
-
|
|
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)
|
librelane/flows/synth_explore.py
CHANGED
librelane/pdk_hashes.yaml
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
sky130:
|
|
2
|
-
gf180mcu:
|
|
3
|
-
ihp-
|
|
1
|
+
sky130: 792ef67037d74c8c51811eab3ce23cf793491296
|
|
2
|
+
gf180mcu: 792ef67037d74c8c51811eab3ce23cf793491296
|
|
3
|
+
ihp-sg13: 89d42ee6d2fd9b50b86a1aada6fee6673c3e6008
|
|
4
|
+
freepdk45: 784b1a483a5f4de362d6f3629378de1199453f3c
|
|
@@ -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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
52
|
+
if { $::env(DESIGN_REPAIR_MAX_UTILIZATION) > 0 } {
|
|
53
53
|
lappend arg_list -max_utilization $::env(DESIGN_REPAIR_MAX_UTILIZATION)
|
|
54
54
|
}
|
|
55
|
-
if {
|
|
56
|
-
lappend arg_list -
|
|
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 {
|
|
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
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
*
|
|
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:
|
librelane/steps/klayout.py
CHANGED
|
@@ -459,10 +459,13 @@ class DRC(KLayoutStep):
|
|
|
459
459
|
deprecated_names=["KLAYOUT_DRC_TECH_SCRIPT"],
|
|
460
460
|
),
|
|
461
461
|
Variable(
|
|
462
|
-
"
|
|
463
|
-
Optional[Dict[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["
|
|
509
|
-
for k, v in self.config["
|
|
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["
|
|
570
|
-
beol = str(self.config["
|
|
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["
|
|
575
|
+
self.config["KLAYOUT_DRC_DEFINES"]["floating_metal"]
|
|
573
576
|
).lower()
|
|
574
|
-
offgrid = str(self.config["
|
|
575
|
-
seal = str(self.config["
|
|
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["
|
|
652
|
-
for k, v in self.config["
|
|
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["
|
|
721
|
-
for k, v in self.config["
|
|
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
|
-
"
|
|
1041
|
-
Optional[Dict[str,
|
|
1042
|
-
"Options passed directly to the KLayout filler
|
|
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["
|
|
1080
|
-
for k, v in self.config["
|
|
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
|
-
"
|
|
1165
|
-
Optional[Dict[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["
|
|
1206
|
-
for k, v in self.config["
|
|
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
|
-
"
|
|
1283
|
-
Optional[Dict[str,
|
|
1284
|
-
"Options passed directly to the KLayout
|
|
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["
|
|
1318
|
-
for k, v in self.config["
|
|
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",
|
librelane/steps/openroad.py
CHANGED
|
@@ -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"]
|
|
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 =
|
|
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
|
-
|
|
342
|
-
|
|
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
|
-
|
|
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(
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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
|
|
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
|
librelane/steps/verilator.py
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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=
|
|
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=
|
|
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
|
|
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=
|
|
21
|
-
librelane/config/__main__.py,sha256=
|
|
22
|
-
librelane/config/config.py,sha256=
|
|
23
|
-
librelane/config/flow.py,sha256=
|
|
24
|
-
librelane/config/pdk_compat.py,sha256=
|
|
25
|
-
librelane/config/preprocessor.py,sha256=
|
|
26
|
-
librelane/config/removals.py,sha256=
|
|
27
|
-
librelane/config/variable.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
142
|
-
librelane/scripts/openroad/repair_design_postgrt.tcl,sha256=
|
|
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=
|
|
154
|
-
librelane/scripts/pyosys/ys_common.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
172
|
-
librelane/steps/step.py,sha256=
|
|
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=
|
|
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.
|
|
177
|
-
librelane-3.1.0.
|
|
178
|
-
librelane-3.1.0.
|
|
179
|
-
librelane-3.1.0.
|
|
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,,
|
|
File without changes
|