librelane 2.4.0.dev7__py3-none-any.whl → 3.0.0.dev22__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (63) hide show
  1. librelane/__main__.py +12 -15
  2. librelane/common/__init__.py +1 -1
  3. librelane/common/drc.py +88 -7
  4. librelane/common/misc.py +6 -6
  5. librelane/common/toolbox.py +1 -1
  6. librelane/config/config.py +5 -1
  7. librelane/config/flow.py +51 -66
  8. librelane/config/pdk_compat.py +79 -2
  9. librelane/config/preprocessor.py +1 -1
  10. librelane/config/variable.py +2 -2
  11. librelane/flows/classic.py +1 -0
  12. librelane/flows/flow.py +3 -6
  13. librelane/flows/sequential.py +85 -40
  14. librelane/plugins.py +1 -1
  15. librelane/scripts/magic/common/read.tcl +2 -2
  16. librelane/scripts/magic/gds/extras_mag.tcl +2 -2
  17. librelane/scripts/odbpy/diodes.py +2 -2
  18. librelane/scripts/openroad/common/dpl.tcl +1 -1
  19. librelane/scripts/openroad/common/grt.tcl +3 -3
  20. librelane/scripts/openroad/common/io.tcl +163 -45
  21. librelane/scripts/openroad/common/resizer.tcl +1 -40
  22. librelane/scripts/openroad/common/set_global_connections.tcl +2 -2
  23. librelane/scripts/openroad/common/set_power_nets.tcl +1 -1
  24. librelane/scripts/openroad/common/set_rc.tcl +159 -40
  25. librelane/scripts/openroad/cts.tcl +37 -6
  26. librelane/scripts/openroad/cut_rows.tcl +19 -4
  27. librelane/scripts/openroad/drt.tcl +59 -8
  28. librelane/scripts/openroad/dump_rc.tcl +105 -0
  29. librelane/scripts/openroad/fill.tcl +2 -2
  30. librelane/scripts/openroad/floorplan.tcl +5 -3
  31. librelane/scripts/openroad/gpl.tcl +7 -8
  32. librelane/scripts/openroad/gui.tcl +22 -2
  33. librelane/scripts/openroad/insert_buffer.tcl +2 -2
  34. librelane/scripts/openroad/ioplacer.tcl +1 -2
  35. librelane/scripts/openroad/irdrop.tcl +3 -3
  36. librelane/scripts/openroad/pdn.tcl +17 -18
  37. librelane/scripts/openroad/rcx.tcl +1 -1
  38. librelane/scripts/openroad/repair_design.tcl +14 -7
  39. librelane/scripts/openroad/repair_design_postgrt.tcl +13 -6
  40. librelane/scripts/openroad/rsz_timing_postcts.tcl +13 -12
  41. librelane/scripts/openroad/rsz_timing_postgrt.tcl +13 -12
  42. librelane/scripts/openroad/sta/check_macro_instances.tcl +1 -1
  43. librelane/scripts/openroad/tapcell.tcl +13 -6
  44. librelane/scripts/openroad/ungpl.tcl +23 -0
  45. librelane/state/__init__.py +1 -1
  46. librelane/state/design_format.py +194 -142
  47. librelane/state/state.py +20 -21
  48. librelane/steps/checker.py +12 -1
  49. librelane/steps/common_variables.py +4 -4
  50. librelane/steps/cvc_rv.py +1 -1
  51. librelane/steps/klayout.py +14 -6
  52. librelane/steps/magic.py +18 -2
  53. librelane/steps/misc.py +1 -1
  54. librelane/steps/odb.py +50 -31
  55. librelane/steps/openroad.py +455 -128
  56. librelane/steps/pyosys.py +20 -5
  57. librelane/steps/step.py +17 -20
  58. librelane/steps/tclstep.py +9 -7
  59. librelane/steps/yosys.py +1 -1
  60. {librelane-2.4.0.dev7.dist-info → librelane-3.0.0.dev22.dist-info}/METADATA +1 -1
  61. {librelane-2.4.0.dev7.dist-info → librelane-3.0.0.dev22.dist-info}/RECORD +63 -61
  62. {librelane-2.4.0.dev7.dist-info → librelane-3.0.0.dev22.dist-info}/WHEEL +0 -0
  63. {librelane-2.4.0.dev7.dist-info → librelane-3.0.0.dev22.dist-info}/entry_points.txt +0 -0
@@ -23,30 +23,29 @@ read_pdn_cfg
23
23
  set arg_list [list]
24
24
  if { $::env(FP_PDN_SKIPTRIM) } {
25
25
  lappend arg_list -skip_trim
26
- puts "adding -skip_trim to pdngen"
27
26
  }
28
27
  # run PDNGEN
29
- if {[catch {pdngen {*}$arg_list} errmsg]} {
28
+ if {[catch {log_cmd pdngen {*}$arg_list} errmsg]} {
30
29
  puts stderr $errmsg
31
- exit 1
32
- }
30
+ exit_unless_gui 1
31
+ } else {
32
+ write_views
33
+ report_design_area_metrics
33
34
 
34
- write_views
35
- report_design_area_metrics
35
+ foreach {net} "$::env(VDD_NETS) $::env(GND_NETS)" {
36
+ set report_file $::env(STEP_DIR)/$net-grid-errors.rpt
36
37
 
37
- foreach {net} "$::env(VDD_NETS) $::env(GND_NETS)" {
38
- set report_file $::env(STEP_DIR)/$net-grid-errors.rpt
38
+ # For some reason, check_power_grid is… totally okay if no nodes are found
39
+ # at all. i.e. PDN generation has completely failed.
40
+ # This is a fallback file.
41
+ set f [open $report_file "w"]
42
+ puts $f ""
43
+ close $f
39
44
 
40
- # For some reason, check_power_grid is… totally okay if no nodes are found
41
- # at all. i.e. PDN generation has completely failed.
42
- # This is a fallback file.
43
- set f [open $report_file "w"]
44
- puts $f "violation type: no nodes"
45
- puts $f " srcs: "
46
- puts $f " - N/A"
47
- close $f
45
+ if { [catch {check_power_grid -net $net -error_file $report_file} err] } {
46
+ puts stderr "\[WARNING\] Grid check for $net failed: $err"
47
+ }
48
48
 
49
- if { [catch {check_power_grid -net $net -error_file $report_file} err] } {
50
- puts stderr "\[WARNING\] Grid check for $net failed: $err"
51
49
  }
50
+
52
51
  }
@@ -26,7 +26,7 @@ if { !$::env(RCX_MERGE_VIA_WIRE_RES) } {
26
26
  # RCX
27
27
  puts "Using RCX ruleset '$::env(RCX_RULESET)'…"
28
28
  define_process_corner -ext_model_index 0 CURRENT_CORNER
29
- extract_parasitics $rcx_flags\
29
+ log_cmd extract_parasitics $rcx_flags\
30
30
  -ext_model_file $::env(RCX_RULESET)\
31
31
  -lef_res
32
32
  write_views
@@ -14,7 +14,6 @@
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  source $::env(SCRIPTS_DIR)/openroad/common/resizer.tcl
16
16
 
17
- load_rsz_corners
18
17
  read_current_odb
19
18
 
20
19
  unset_propagated_clock [all_clocks]
@@ -42,17 +41,25 @@ if { $::env(DESIGN_REPAIR_BUFFER_OUTPUT_PORTS) } {
42
41
  buffer_ports -outputs
43
42
  }
44
43
 
44
+ set arg_list [list]
45
+ lappend arg_list -verbose
46
+ lappend arg_list -max_wire_length $::env(DESIGN_REPAIR_MAX_WIRE_LENGTH)
47
+ lappend arg_list -slew_margin $::env(DESIGN_REPAIR_MAX_SLEW_PCT)
48
+ lappend arg_list -cap_margin $::env(DESIGN_REPAIR_MAX_CAP_PCT)
49
+ if { [info exists ::env(DESIGN_REPAIR_MAX_UTILIZATION)] } {
50
+ lappend arg_list -max_utilization $::env(DESIGN_REPAIR_MAX_UTILIZATION)
51
+ }
52
+ if { [info exists ::env(DESIGN_REPAIR_BUFFER_GAIN)] } {
53
+ lappend arg_list -buffer_gain $::env(DESIGN_REPAIR_BUFFER_GAIN)
54
+ }
45
55
  # Repair Design
46
- repair_design -verbose \
47
- -max_wire_length $::env(DESIGN_REPAIR_MAX_WIRE_LENGTH) \
48
- -slew_margin $::env(DESIGN_REPAIR_MAX_SLEW_PCT) \
49
- -cap_margin $::env(DESIGN_REPAIR_MAX_CAP_PCT)
56
+ log_cmd repair_design {*}$arg_list
50
57
 
51
58
  if { $::env(DESIGN_REPAIR_TIE_FANOUT) } {
52
59
  # repair tie lo fanout
53
- repair_tie_fanout -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIELO_CELL)
60
+ repair_tie_fanout -verbose -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIELO_CELL)
54
61
  # repair tie hi fanout
55
- repair_tie_fanout -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIEHI_CELL)
62
+ repair_tie_fanout -verbose -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIEHI_CELL)
56
63
  }
57
64
 
58
65
  report_floating_nets -verbose
@@ -14,7 +14,6 @@
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  source $::env(SCRIPTS_DIR)/openroad/common/resizer.tcl
16
16
 
17
- load_rsz_corners
18
17
  read_current_odb
19
18
 
20
19
  set_propagated_clock [all_clocks]
@@ -31,11 +30,19 @@ source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl
31
30
  #}
32
31
  estimate_parasitics -global_routing
33
32
 
34
- # Repair design
35
- repair_design -verbose \
36
- -max_wire_length $::env(GRT_DESIGN_REPAIR_MAX_WIRE_LENGTH) \
37
- -slew_margin $::env(GRT_DESIGN_REPAIR_MAX_SLEW_PCT) \
38
- -cap_margin $::env(GRT_DESIGN_REPAIR_MAX_CAP_PCT)
33
+ # Repair Design
34
+ set arg_list [list]
35
+ lappend arg_list -verbose
36
+ lappend arg_list -max_wire_length $::env(GRT_DESIGN_REPAIR_MAX_WIRE_LENGTH)
37
+ lappend arg_list -slew_margin $::env(GRT_DESIGN_REPAIR_MAX_SLEW_PCT)
38
+ lappend arg_list -cap_margin $::env(GRT_DESIGN_REPAIR_MAX_CAP_PCT)
39
+ if { [info exists ::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION)] } {
40
+ lappend arg_list -max_utilization $::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION)
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
+ log_cmd repair_design {*}$arg_list
39
46
 
40
47
  # Re-DPL and GRT
41
48
  source $::env(SCRIPTS_DIR)/openroad/common/dpl.tcl
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Efabless Corporation
1
+ # Copyright 2020-2024 Efabless Corporation
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  source $::env(SCRIPTS_DIR)/openroad/common/resizer.tcl
16
16
 
17
- load_rsz_corners
18
17
  read_current_odb
19
18
 
20
19
  set_propagated_clock [all_clocks]
@@ -34,9 +33,11 @@ lappend setup_args -verbose
34
33
  lappend setup_args -setup
35
34
  lappend setup_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN)
36
35
  lappend setup_args -max_buffer_percent $::env(PL_RESIZER_SETUP_MAX_BUFFER_PCT)
37
- if { $::env(PL_RESIZER_GATE_CLONING) != 1 } {
38
- lappend setup_args -skip_gate_cloning
39
- }
36
+ append_if_not_flag setup_args PL_RESIZER_SETUP_BUFFERING -skip_buffering
37
+ append_if_not_flag setup_args PL_RESIZER_SETUP_BUFFER_REMOVAL -skip_buffer_removal
38
+ append_if_not_flag setup_args PL_RESIZER_SETUP_GATE_CLONING -skip_gate_cloning
39
+ append_if_exists_argument setup_args PL_RESIZER_SETUP_REPAIR_TNS_PCT -repair_tns
40
+ append_if_exists_argument setup_args PL_RESIZER_SETUP_MAX_UTIL_PCT -max_utilization
40
41
 
41
42
  set hold_args [list]
42
43
  lappend hold_args -verbose
@@ -44,16 +45,16 @@ lappend hold_args -hold
44
45
  lappend hold_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN)
45
46
  lappend hold_args -hold_margin $::env(PL_RESIZER_HOLD_SLACK_MARGIN)
46
47
  lappend hold_args -max_buffer_percent $::env(PL_RESIZER_HOLD_MAX_BUFFER_PCT)
47
- if { $::env(PL_RESIZER_ALLOW_SETUP_VIOS) == 1 } {
48
- lappend hold_args -allow_setup_violations
49
- }
48
+ append_if_flag hold_args PL_RESIZER_ALLOW_SETUP_VIOS -allow_setup_violations
49
+ append_if_exists_argument hold_args PL_RESIZER_HOLD_REPAIR_TNS_PCT -repair_tns
50
+ append_if_exists_argument hold_args PL_RESIZER_HOLD_MAX_UTIL_PCT -max_utilization
50
51
 
51
52
  if { $::env(PL_RESIZER_FIX_HOLD_FIRST) == 1 } {
52
- repair_timing {*}$hold_args
53
- repair_timing {*}$setup_args
53
+ log_cmd repair_timing {*}$hold_args
54
+ log_cmd repair_timing {*}$setup_args
54
55
  } else {
55
- repair_timing {*}$setup_args
56
- repair_timing {*}$hold_args
56
+ log_cmd repair_timing {*}$setup_args
57
+ log_cmd repair_timing {*}$hold_args
57
58
  }
58
59
 
59
60
  # Legalize
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Efabless Corporation
1
+ # Copyright 2020-2024 Efabless Corporation
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  source $::env(SCRIPTS_DIR)/openroad/common/resizer.tcl
16
16
 
17
- load_rsz_corners
18
17
  read_current_odb
19
18
 
20
19
  set_propagated_clock [all_clocks]
@@ -37,9 +36,11 @@ lappend setup_args -verbose
37
36
  lappend setup_args -setup
38
37
  lappend setup_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN)
39
38
  lappend setup_args -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT)
40
- if { $::env(GRT_RESIZER_GATE_CLONING) != 1 } {
41
- lappend setup_args -skip_gate_cloning
42
- }
39
+ append_if_not_flag setup_args GRT_RESIZER_SETUP_BUFFERING -skip_buffering
40
+ append_if_not_flag setup_args GRT_RESIZER_SETUP_BUFFER_REMOVAL -skip_buffer_removal
41
+ append_if_not_flag setup_args GRT_RESIZER_SETUP_GATE_CLONING -skip_gate_cloning
42
+ append_if_exists_argument setup_args GRT_RESIZER_SETUP_REPAIR_TNS_PCT -repair_tns
43
+ append_if_exists_argument setup_args GRT_RESIZER_SETUP_MAX_UTIL_PCT -max_utilization
43
44
 
44
45
  set hold_args [list]
45
46
  lappend hold_args -verbose
@@ -47,16 +48,16 @@ lappend hold_args -hold
47
48
  lappend hold_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN)
48
49
  lappend hold_args -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN)
49
50
  lappend hold_args -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT)
50
- if { $::env(GRT_RESIZER_ALLOW_SETUP_VIOS) == 1 } {
51
- lappend hold_args -allow_setup_violations
52
- }
51
+ append_if_flag hold_args GRT_RESIZER_ALLOW_SETUP_VIOS -allow_setup_violations
52
+ append_if_exists_argument hold_args GRT_RESIZER_HOLD_REPAIR_TNS_PCT -repair_tns
53
+ append_if_exists_argument hold_args GRT_RESIZER_HOLD_MAX_UTIL_PCT -max_utilization
53
54
 
54
55
  if { $::env(GRT_RESIZER_FIX_HOLD_FIRST) == 1 } {
55
- repair_timing {*}$hold_args
56
- repair_timing {*}$setup_args
56
+ log_cmd repair_timing {*}$hold_args
57
+ log_cmd repair_timing {*}$setup_args
57
58
  } else {
58
- repair_timing {*}$setup_args
59
- repair_timing {*}$hold_args
59
+ log_cmd repair_timing {*}$setup_args
60
+ log_cmd repair_timing {*}$hold_args
60
61
  }
61
62
 
62
63
  # Re-DPL and GRT
@@ -49,5 +49,5 @@ foreach {instance_name macro_name} $::env(_check_macro_instances) {
49
49
  }
50
50
 
51
51
  if { $error_count != 0 } {
52
- exit -1
52
+ exit_unless_gui 1
53
53
  }
@@ -14,12 +14,19 @@
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  read_current_odb
16
16
 
17
- tapcell\
18
- -distance $::env(FP_TAPCELL_DIST)\
19
- -tapcell_master "$::env(WELLTAP_CELL)"\
20
- -endcap_master "$::env(ENDCAP_CELL)"\
21
- -halo_width_x $::env(FP_MACRO_HORIZONTAL_HALO)\
22
- -halo_width_y $::env(FP_MACRO_VERTICAL_HALO)
17
+ set tapcell_args [list]
18
+ append_if_exists_argument tapcell_args FP_TAPCELL_DIST -distance
19
+ append_if_exists_argument tapcell_args WELLTAP_CELL -tapcell_master
20
+ append_if_exists_argument tapcell_args ENDCAP_CELL -endcap_master
23
21
 
22
+ if { [llength tapcell_args] } {
23
+ log_cmd tapcell\
24
+ -halo_width_x $::env(FP_MACRO_HORIZONTAL_HALO)\
25
+ -halo_width_y $::env(FP_MACRO_VERTICAL_HALO)\
26
+ {*}$tapcell_args
27
+
28
+ } else {
29
+ puts "\[INFO\] WELLTAP_CELL and ENDCAP_CELL both unspecified. Doing nothing."
30
+ }
24
31
 
25
32
  write_views
@@ -0,0 +1,23 @@
1
+ # Copyright 2024 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
+ read_current_odb
16
+
17
+ set ::insts [$::block getInsts]
18
+
19
+ foreach inst $::insts {
20
+ $inst setPlacementStatus "NONE"
21
+ }
22
+
23
+ write_views
@@ -20,5 +20,5 @@ This module manages the State of a Design before and after the execution of an
20
20
  LibreLane step. The State is essentially a list of views in various formats in
21
21
  addition to the cumulative set of metrics created by previous Steps.
22
22
  """
23
- from .design_format import DesignFormat, DesignFormatObject
23
+ from .design_format import DesignFormat
24
24
  from .state import State, InvalidState, StateElement
@@ -11,26 +11,38 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- from enum import Enum
15
- from typing import Dict, Optional
16
- from dataclasses import dataclass, replace
14
+ from __future__ import annotations
15
+ from dataclasses import dataclass, field, replace
16
+ from typing import Dict, List, Optional, ClassVar
17
+ from deprecated.sphinx import deprecated
18
+
19
+
20
+ class DFMetaclass(type):
21
+ def __getattr__(Self, key: str):
22
+ if df := Self.factory.get(key):
23
+ return df
24
+ raise AttributeError(
25
+ "Unknown DesignFormat or Type[DesignFormat] attribute",
26
+ key,
27
+ Self,
28
+ )
17
29
 
18
30
 
19
31
  @dataclass
20
- class DesignFormatObject:
32
+ class DesignFormat(metaclass=DFMetaclass):
21
33
  """
22
34
  Metadata about the various possible text or binary representations (views)
23
35
  of any design.
24
36
 
25
- For example, ``DesignFormat.NETLIST.value`` has the metadata for Netlist
26
- views.
37
+ For example, ``DesignFormat.nl`` has the metadata for Netlist views.
27
38
 
28
- :param id: A lowercase alphanumeric identifier for the design format.
29
- Some IDs in LibreLane 2.X use dashes. This is an inconsistency that will
30
- be addressed in the next major version of LibreLane as it would be a
31
- breaking change.
39
+ :param id: A lowercase alphanumeric/underscore identifier for the design
40
+ format.
32
41
  :param extension: The file extension for designs saved in this format.
33
- :param name: A human-readable name for this design format.
42
+ :param full_name: A human-readable name for this design format.
43
+ :param alts: A list of alternate ids used to access the DesignFormat by
44
+ the subscript operator. Includes its OpenLane <3.0.0 enumeration name
45
+ for limited backwards compatibility.
34
46
  :param folder_override: The subdirectory when
35
47
  :meth:`librelane.state.State.save_snapshot` is called on a state. If
36
48
  unset, the value for ``id`` will be used.
@@ -40,7 +52,8 @@ class DesignFormatObject:
40
52
 
41
53
  id: str
42
54
  extension: str
43
- name: str
55
+ full_name: str
56
+ alts: List[str] = field(default_factory=list)
44
57
  folder_override: Optional[str] = None
45
58
  multiple: bool = False
46
59
 
@@ -51,145 +64,184 @@ class DesignFormatObject:
51
64
  return self.folder_override or self.id
52
65
 
53
66
  @property
54
- def optional(self) -> bool:
55
- return self._instance_optional
56
-
57
-
58
- class DesignFormat(Enum):
59
- """
60
- An `enumeration <https://docs.python.org/3/library/enum.html>`_ of a number
61
- of :class:`librelane.state.DesignFormatObject`\\s representing the various
62
- possible text or binary representations (views) supported by LibreLane
63
- states.
64
-
65
- Members of this enumeration are used as the keys of
66
- :class:`librelane.state.State` objects.
67
- """
68
-
69
- NETLIST: DesignFormatObject = DesignFormatObject(
70
- "nl",
71
- "nl.v",
72
- "Verilog Netlist",
73
- )
74
- POWERED_NETLIST: DesignFormatObject = DesignFormatObject(
75
- "pnl",
76
- "pnl.v",
77
- "Powered Verilog Netlist",
78
- )
79
- POWERED_NETLIST_SDF_FRIENDLY: DesignFormatObject = DesignFormatObject(
80
- "pnl-sdf-friendly",
81
- "pnl-sdf.v",
82
- "Powered Verilog Netlist For SDF Simulation (Without Fill Cells)",
83
- folder_override="pnl",
84
- )
85
- POWERED_NETLIST_NO_PHYSICAL_CELLS: DesignFormatObject = DesignFormatObject(
86
- "pnl-npc",
87
- "pnl-npc.v",
88
- "Powered Verilog Netlist Without Physical Cells (Fill Cells and Diode Cells)",
89
- folder_override="pnl",
90
- )
91
-
92
- DEF: DesignFormatObject = DesignFormatObject(
93
- "def",
94
- "def",
95
- "Design Exchange Format",
96
- )
97
- LEF: DesignFormatObject = DesignFormatObject(
98
- "lef",
99
- "lef",
100
- "Library Exchange Format",
101
- )
102
- OPENROAD_LEF: DesignFormatObject = DesignFormatObject(
103
- "openroad-lef",
104
- "openroad.lef",
105
- "Library Exchange Format Generated by OpenROAD",
106
- folder_override="lef",
107
- )
108
- ODB: DesignFormatObject = DesignFormatObject(
109
- "odb",
110
- "odb",
111
- "OpenDB Database",
67
+ @deprecated(
68
+ "The DesignFormat is directly returned now, no need for .value",
69
+ version="3.0.0",
70
+ action="once",
112
71
  )
72
+ def value(self) -> DesignFormat:
73
+ return self
113
74
 
114
- SDC: DesignFormatObject = DesignFormatObject(
115
- "sdc",
116
- "sdc",
117
- "Design Constraints",
118
- )
119
- SDF: DesignFormatObject = DesignFormatObject(
120
- "sdf",
121
- "sdf",
122
- "Standard Delay Format",
123
- multiple=True,
124
- )
125
- SPEF: DesignFormatObject = DesignFormatObject(
126
- "spef",
127
- "spef",
128
- "Standard Parasitics Extraction Format",
129
- multiple=True, # nom, min, max, ...
130
- )
131
- LIB: DesignFormatObject = DesignFormatObject(
132
- "lib",
133
- "lib",
134
- "LIB Timing Library Format",
135
- multiple=True,
136
- )
137
- SPICE: DesignFormatObject = DesignFormatObject(
138
- "spice",
139
- "spice",
140
- "Simulation Program with Integrated Circuit Emphasis",
141
- )
142
-
143
- MAG: DesignFormatObject = DesignFormatObject(
144
- "mag",
145
- "mag",
146
- "Magic VLSI View",
147
- )
75
+ @property
76
+ def optional(self) -> bool:
77
+ return self._instance_optional
148
78
 
149
- GDS: DesignFormatObject = DesignFormatObject(
150
- "gds",
151
- "gds",
152
- "GDSII Stream",
153
- )
154
- MAG_GDS: DesignFormatObject = DesignFormatObject(
155
- "mag_gds",
156
- "magic.gds",
157
- "GDSII Stream (Magic)",
158
- )
159
- KLAYOUT_GDS: DesignFormatObject = DesignFormatObject(
160
- "klayout_gds",
161
- "klayout.gds",
162
- "GDSII Stream (KLayout)",
79
+ @property
80
+ @deprecated(
81
+ ".name has been removed because it's redundant, use .id",
82
+ version="3.0.0",
83
+ action="once",
163
84
  )
85
+ def name(self) -> str:
86
+ return self.id
164
87
 
165
- JSON_HEADER: DesignFormatObject = DesignFormatObject(
166
- "json_h",
167
- "h.json",
168
- "Design JSON Header File",
169
- )
170
- VERILOG_HEADER: DesignFormatObject = DesignFormatObject(
171
- "vh",
172
- "vh",
173
- "Verilog Header",
174
- )
88
+ def register(self):
89
+ self.__class__.factory.register(self)
175
90
 
176
91
  def __str__(self) -> str:
177
- return self.value.id
92
+ return self.id
93
+
94
+ def __hash__(self):
95
+ return hash(self.id)
178
96
 
179
97
  @staticmethod
98
+ @deprecated(
99
+ "Use DesignFormat.factory.get",
100
+ version="3.0.0",
101
+ action="once",
102
+ )
180
103
  def by_id(id: str) -> Optional["DesignFormat"]:
181
- return _designformat_by_id.get(id)
104
+ return DesignFormat.factory.get(id)
105
+
106
+ class DesignFormatFactory(object):
107
+ """
108
+ A factory singleton for DesignFormats, allowing them to be registered
109
+ and then retrieved by a string name.
110
+
111
+ See https://en.wikipedia.org/wiki/Factory_(object-oriented_programming) for
112
+ a primer.
113
+ """
114
+
115
+ _registry: ClassVar[Dict[str, DesignFormat]] = {}
116
+
117
+ @classmethod
118
+ def register(Self, df: DesignFormat) -> DesignFormat:
119
+ """
120
+ Adds a DesignFormat to the registry using its
121
+ :attr:`DesignFormat.id`, :attr:`DesignFormat.name` and
122
+ :attr:`DesignFormat.alts` attributes.
123
+ """
124
+ Self._registry[df.id] = df
125
+ for alt in df.alts:
126
+ Self._registry[alt] = df
127
+ return df
128
+
129
+ @classmethod
130
+ def get(Self, name: str) -> Optional[DesignFormat]:
131
+ """
132
+ Retrieves a DesignFormat type from the registry using a lookup
133
+ string.
134
+
135
+ :param name: The registered name of the Step. Case-insensitive.
136
+ """
137
+ return Self._registry.get(name)
138
+
139
+ @classmethod
140
+ def list(Self) -> List[str]:
141
+ """
142
+ :returns: A list of IDs of all registered DesignFormat.
143
+ """
144
+ return [cls.id for cls in Self._registry.values()]
145
+
146
+ factory: ClassVar = DesignFormatFactory
182
147
 
183
148
  def mkOptional(self) -> "DesignFormat":
184
- # HACK: Create ephemeral DesignFormat copy until 3.0.0 lets us do this
185
- # a bit more appropriately.
186
- clone = object.__new__(DesignFormat)
187
- clone._name_ = self._name_
188
- clone._value_ = replace(self._value_)
189
- clone._value_._instance_optional = True
190
- return clone
191
-
192
-
193
- _designformat_by_id: Dict[str, "DesignFormat"] = {
194
- format.value.id: format for format in DesignFormat
195
- }
149
+ return replace(self, _instance_optional=True)
150
+
151
+
152
+ # Common Design Formats
153
+ DesignFormat(
154
+ "nl",
155
+ "nl.v",
156
+ "Verilog Netlist",
157
+ alts=["NETLIST"],
158
+ ).register()
159
+
160
+ DesignFormat(
161
+ "pnl",
162
+ "pnl.v",
163
+ "Powered Verilog Netlist",
164
+ alts=["POWERED_NETLIST"],
165
+ ).register()
166
+
167
+ DesignFormat(
168
+ "sdf_pnl",
169
+ "sdf_pnl.v",
170
+ "Powered Verilog Netlist for SDF Simulation (No Fills)",
171
+ alts=["SDF_FRIENDLY_POWERED_NETLIST"],
172
+ folder_override="pnl",
173
+ ).register()
174
+
175
+ DesignFormat(
176
+ "logical_pnl",
177
+ "logical_pnl.v",
178
+ "Logical cell-only Powered Verilog Netlist",
179
+ alts=["LOGICAL_POWERED_NETLIST"],
180
+ folder_override="pnl",
181
+ ).register()
182
+
183
+ DesignFormat(
184
+ "def",
185
+ "def",
186
+ "Design Exchange Format",
187
+ alts=["def_", "DEF"],
188
+ ).register()
189
+
190
+ DesignFormat(
191
+ "lef",
192
+ "lef",
193
+ "Library Exchange Format",
194
+ alts=["LEF"],
195
+ ).register()
196
+
197
+ DesignFormat(
198
+ "sdc",
199
+ "sdc",
200
+ "Design Constraints",
201
+ alts=["SDC"],
202
+ ).register()
203
+
204
+ DesignFormat(
205
+ "sdf",
206
+ "sdf",
207
+ "Standard Delay Format",
208
+ alts=["SDF"],
209
+ multiple=True,
210
+ ).register()
211
+
212
+ DesignFormat(
213
+ "spef",
214
+ "spef",
215
+ "Standard Parasitics Extraction Format",
216
+ alts=["SPEF"],
217
+ multiple=True, # nom, min, max, ...
218
+ ).register()
219
+
220
+ DesignFormat(
221
+ "lib",
222
+ "lib",
223
+ "LIB Timing Library Format",
224
+ alts=["LIB"],
225
+ multiple=True,
226
+ ).register()
227
+
228
+ DesignFormat(
229
+ "spice",
230
+ "spice",
231
+ "Simulation Program with Integrated Circuit Emphasis",
232
+ alts=["SPICE"],
233
+ ).register()
234
+
235
+ DesignFormat(
236
+ "gds",
237
+ "gds",
238
+ "GDSII Stream",
239
+ alts=["GDS"],
240
+ ).register()
241
+
242
+ DesignFormat(
243
+ "vh",
244
+ "vh",
245
+ "Verilog Header",
246
+ alts=["VERILOG_HEADER"],
247
+ ).register()