librelane 2.4.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (170) hide show
  1. librelane/__init__.py +38 -0
  2. librelane/__main__.py +479 -0
  3. librelane/__version__.py +43 -0
  4. librelane/common/__init__.py +63 -0
  5. librelane/common/cli.py +75 -0
  6. librelane/common/drc.py +246 -0
  7. librelane/common/generic_dict.py +319 -0
  8. librelane/common/metrics/__init__.py +35 -0
  9. librelane/common/metrics/__main__.py +413 -0
  10. librelane/common/metrics/library.py +354 -0
  11. librelane/common/metrics/metric.py +186 -0
  12. librelane/common/metrics/util.py +279 -0
  13. librelane/common/misc.py +456 -0
  14. librelane/common/ring_buffer.py +63 -0
  15. librelane/common/tcl.py +80 -0
  16. librelane/common/toolbox.py +549 -0
  17. librelane/common/tpe.py +41 -0
  18. librelane/common/types.py +116 -0
  19. librelane/config/__init__.py +32 -0
  20. librelane/config/__main__.py +155 -0
  21. librelane/config/config.py +1025 -0
  22. librelane/config/flow.py +490 -0
  23. librelane/config/pdk_compat.py +255 -0
  24. librelane/config/preprocessor.py +464 -0
  25. librelane/config/removals.py +45 -0
  26. librelane/config/variable.py +743 -0
  27. librelane/container.py +285 -0
  28. librelane/env_info.py +320 -0
  29. librelane/examples/spm/config.yaml +33 -0
  30. librelane/examples/spm/pin_order.cfg +14 -0
  31. librelane/examples/spm/src/impl.sdc +73 -0
  32. librelane/examples/spm/src/signoff.sdc +68 -0
  33. librelane/examples/spm/src/spm.v +73 -0
  34. librelane/examples/spm/verify/spm_tb.v +106 -0
  35. librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
  36. librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
  37. librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
  38. librelane/examples/spm-user_project_wrapper/config.json +13 -0
  39. librelane/examples/spm-user_project_wrapper/defines.v +66 -0
  40. librelane/examples/spm-user_project_wrapper/template.def +7656 -0
  41. librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
  42. librelane/flows/__init__.py +24 -0
  43. librelane/flows/builtins.py +18 -0
  44. librelane/flows/classic.py +327 -0
  45. librelane/flows/cli.py +463 -0
  46. librelane/flows/flow.py +1049 -0
  47. librelane/flows/misc.py +71 -0
  48. librelane/flows/optimizing.py +179 -0
  49. librelane/flows/sequential.py +367 -0
  50. librelane/flows/synth_explore.py +173 -0
  51. librelane/help/__main__.py +39 -0
  52. librelane/logging/__init__.py +40 -0
  53. librelane/logging/logger.py +323 -0
  54. librelane/open_pdks_rev +1 -0
  55. librelane/plugins.py +21 -0
  56. librelane/py.typed +0 -0
  57. librelane/scripts/base.sdc +80 -0
  58. librelane/scripts/klayout/Readme.md +2 -0
  59. librelane/scripts/klayout/open_design.py +63 -0
  60. librelane/scripts/klayout/render.py +121 -0
  61. librelane/scripts/klayout/stream_out.py +176 -0
  62. librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
  63. librelane/scripts/klayout/xor.drc +120 -0
  64. librelane/scripts/magic/Readme.md +1 -0
  65. librelane/scripts/magic/common/read.tcl +114 -0
  66. librelane/scripts/magic/def/antenna_check.tcl +35 -0
  67. librelane/scripts/magic/def/mag.tcl +19 -0
  68. librelane/scripts/magic/def/mag_gds.tcl +79 -0
  69. librelane/scripts/magic/drc.tcl +78 -0
  70. librelane/scripts/magic/extract_spice.tcl +98 -0
  71. librelane/scripts/magic/gds/drc_batch.tcl +74 -0
  72. librelane/scripts/magic/gds/erase_box.tcl +32 -0
  73. librelane/scripts/magic/gds/extras_mag.tcl +45 -0
  74. librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
  75. librelane/scripts/magic/get_bbox.tcl +11 -0
  76. librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
  77. librelane/scripts/magic/lef/maglef.tcl +26 -0
  78. librelane/scripts/magic/lef.tcl +57 -0
  79. librelane/scripts/magic/open.tcl +28 -0
  80. librelane/scripts/magic/wrapper.tcl +21 -0
  81. librelane/scripts/netgen/setup.tcl +28 -0
  82. librelane/scripts/odbpy/apply_def_template.py +49 -0
  83. librelane/scripts/odbpy/cell_frequency.py +107 -0
  84. librelane/scripts/odbpy/check_antenna_properties.py +116 -0
  85. librelane/scripts/odbpy/contextualize.py +109 -0
  86. librelane/scripts/odbpy/defutil.py +573 -0
  87. librelane/scripts/odbpy/diodes.py +373 -0
  88. librelane/scripts/odbpy/disconnected_pins.py +305 -0
  89. librelane/scripts/odbpy/eco_buffer.py +181 -0
  90. librelane/scripts/odbpy/eco_diode.py +139 -0
  91. librelane/scripts/odbpy/filter_unannotated.py +100 -0
  92. librelane/scripts/odbpy/io_place.py +482 -0
  93. librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
  94. librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
  95. librelane/scripts/odbpy/label_macro_pins.py +277 -0
  96. librelane/scripts/odbpy/lefutil.py +97 -0
  97. librelane/scripts/odbpy/placers.py +162 -0
  98. librelane/scripts/odbpy/power_utils.py +397 -0
  99. librelane/scripts/odbpy/random_place.py +57 -0
  100. librelane/scripts/odbpy/reader.py +250 -0
  101. librelane/scripts/odbpy/remove_buffers.py +173 -0
  102. librelane/scripts/odbpy/snap_to_grid.py +57 -0
  103. librelane/scripts/odbpy/wire_lengths.py +93 -0
  104. librelane/scripts/openroad/antenna_check.tcl +20 -0
  105. librelane/scripts/openroad/antenna_repair.tcl +31 -0
  106. librelane/scripts/openroad/basic_mp.tcl +24 -0
  107. librelane/scripts/openroad/buffer_list.tcl +10 -0
  108. librelane/scripts/openroad/common/dpl.tcl +24 -0
  109. librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
  110. librelane/scripts/openroad/common/grt.tcl +32 -0
  111. librelane/scripts/openroad/common/io.tcl +540 -0
  112. librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
  113. librelane/scripts/openroad/common/resizer.tcl +103 -0
  114. librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
  115. librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
  116. librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
  117. librelane/scripts/openroad/common/set_rc.tcl +75 -0
  118. librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
  119. librelane/scripts/openroad/cts.tcl +80 -0
  120. librelane/scripts/openroad/cut_rows.tcl +24 -0
  121. librelane/scripts/openroad/dpl.tcl +24 -0
  122. librelane/scripts/openroad/drt.tcl +37 -0
  123. librelane/scripts/openroad/fill.tcl +30 -0
  124. librelane/scripts/openroad/floorplan.tcl +145 -0
  125. librelane/scripts/openroad/gpl.tcl +88 -0
  126. librelane/scripts/openroad/grt.tcl +30 -0
  127. librelane/scripts/openroad/gui.tcl +37 -0
  128. librelane/scripts/openroad/insert_buffer.tcl +127 -0
  129. librelane/scripts/openroad/ioplacer.tcl +67 -0
  130. librelane/scripts/openroad/irdrop.tcl +51 -0
  131. librelane/scripts/openroad/pdn.tcl +52 -0
  132. librelane/scripts/openroad/rcx.tcl +32 -0
  133. librelane/scripts/openroad/repair_design.tcl +70 -0
  134. librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
  135. librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
  136. librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
  137. librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
  138. librelane/scripts/openroad/sta/corner.tcl +393 -0
  139. librelane/scripts/openroad/tapcell.tcl +25 -0
  140. librelane/scripts/openroad/write_views.tcl +27 -0
  141. librelane/scripts/pyosys/construct_abc_script.py +177 -0
  142. librelane/scripts/pyosys/json_header.py +84 -0
  143. librelane/scripts/pyosys/synthesize.py +493 -0
  144. librelane/scripts/pyosys/ys_common.py +153 -0
  145. librelane/scripts/tclsh/hello.tcl +1 -0
  146. librelane/state/__init__.py +24 -0
  147. librelane/state/__main__.py +61 -0
  148. librelane/state/design_format.py +195 -0
  149. librelane/state/state.py +359 -0
  150. librelane/steps/__init__.py +61 -0
  151. librelane/steps/__main__.py +510 -0
  152. librelane/steps/checker.py +637 -0
  153. librelane/steps/common_variables.py +340 -0
  154. librelane/steps/cvc_rv.py +169 -0
  155. librelane/steps/klayout.py +509 -0
  156. librelane/steps/magic.py +576 -0
  157. librelane/steps/misc.py +160 -0
  158. librelane/steps/netgen.py +253 -0
  159. librelane/steps/odb.py +1088 -0
  160. librelane/steps/openroad.py +2460 -0
  161. librelane/steps/openroad_alerts.py +102 -0
  162. librelane/steps/pyosys.py +640 -0
  163. librelane/steps/step.py +1571 -0
  164. librelane/steps/tclstep.py +288 -0
  165. librelane/steps/verilator.py +222 -0
  166. librelane/steps/yosys.py +371 -0
  167. librelane-2.4.0.dist-info/METADATA +169 -0
  168. librelane-2.4.0.dist-info/RECORD +170 -0
  169. librelane-2.4.0.dist-info/WHEEL +4 -0
  170. librelane-2.4.0.dist-info/entry_points.txt +9 -0
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2020 Efabless Corporation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import defutil
16
+ import utl
17
+
18
+ from reader import click_odb, click
19
+
20
+
21
+ @click.command()
22
+ @click.option("-t", "--def-template", required=True, help="Template DEF")
23
+ @click.option(
24
+ "--copy-def-power",
25
+ default=False,
26
+ is_flag=True,
27
+ help="Whether to copy power pins from the DEF template",
28
+ )
29
+ @click.option(
30
+ "--permissive/--strict",
31
+ default=False,
32
+ help="Whether to treat pin matching permissively (ignoring non-matching pins) or strictly (flagging all non-matching pins as errors)",
33
+ )
34
+ @click_odb
35
+ def cli(reader, input_lefs, permissive, copy_def_power, def_template):
36
+ defutil.relocate_pins(
37
+ reader.db,
38
+ input_lefs,
39
+ def_template,
40
+ permissive,
41
+ copy_def_power,
42
+ )
43
+ area = defutil.get_die_area(def_template, input_lefs)
44
+ area_metric = f"{area[0]} {area[1]} {area[2]} {area[3]}"
45
+ utl.metric("design__die__bbox", area_metric)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ cli()
@@ -0,0 +1,107 @@
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
+ import os
15
+ import re
16
+
17
+ from collections import Counter
18
+ from reader import click, click_odb, OdbReader
19
+
20
+ import rich
21
+ from rich.table import Table
22
+ from rich.console import Console
23
+
24
+
25
+ @click.command()
26
+ @click.option(
27
+ "--out-dir",
28
+ type=click.Path(file_okay=False, dir_okay=True),
29
+ required=True,
30
+ help="Directory to output tables to",
31
+ )
32
+ @click.option(
33
+ "--buffer-list",
34
+ type=click.Path(file_okay=True, dir_okay=False),
35
+ help="List of wildcard strings",
36
+ )
37
+ @click_odb
38
+ def main(
39
+ out_dir,
40
+ buffer_list,
41
+ reader: OdbReader,
42
+ ):
43
+ db = reader.db
44
+ block = db.getChip().getBlock()
45
+
46
+ pattern = r"^(\S+)__(\S+)_\d+"
47
+ compiled_pattern = re.compile(pattern)
48
+
49
+ cell_frequency_table = Table(
50
+ "Cell",
51
+ "Count",
52
+ title="Cells by Master",
53
+ )
54
+ scl_table = Table(
55
+ "SCL",
56
+ "Count",
57
+ title="Cells by SCL",
58
+ )
59
+ cell_fn_table = Table(
60
+ "Cell Function",
61
+ "Count",
62
+ title="Cells by Function",
63
+ title_justify="center",
64
+ )
65
+ buffer_table = Table(
66
+ "Buffer",
67
+ "Count",
68
+ title="Buffers by Cell Master",
69
+ )
70
+
71
+ cells = [instance.getMaster().getName() for instance in block.getInsts()]
72
+ buffers = open(buffer_list).read().split()
73
+ buffer_frequency = Counter([cell for cell in cells if cell in buffers])
74
+ cell_frequency = Counter(cells)
75
+ scl_frequency = Counter()
76
+ cell_fn_frequency = Counter()
77
+
78
+ for cell in cell_frequency.keys():
79
+ if match := compiled_pattern.search(cell):
80
+ scl, cell_type = match[1], match[2]
81
+ cell_type_key = f"{scl}__{cell_type}"
82
+ scl_frequency[scl] += cell_frequency[cell]
83
+ cell_fn_frequency[cell_type_key] += cell_frequency[cell]
84
+
85
+ console = Console()
86
+ for table, frequency, name in [
87
+ (cell_frequency_table, cell_frequency, "cell"),
88
+ (cell_fn_table, cell_fn_frequency, "cell_function"),
89
+ (scl_table, scl_frequency, "by_scl"),
90
+ (buffer_table, buffer_frequency, "buffers"),
91
+ ]:
92
+ freqs = sorted(frequency.items(), key=lambda x: x[0])
93
+ for key, value in freqs:
94
+ table.add_row(key, str(value))
95
+
96
+ table.min_width = console.width
97
+ console.print(table)
98
+
99
+ full_table_path = os.path.join(out_dir, f"{name}.rpt")
100
+ table.min_width = 160
101
+ with open(full_table_path, "w") as f:
102
+ file_console = rich.console.Console(file=f, width=160)
103
+ file_console.print(table)
104
+
105
+
106
+ if __name__ == "__main__":
107
+ main()
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2024 Efabless Corporation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import yaml
16
+
17
+ from tempfile import NamedTemporaryFile
18
+ from textwrap import dedent
19
+ from reader import click_odb, click, odb
20
+
21
+
22
+ def check_cells(odb_cells):
23
+ report = []
24
+
25
+ for cell in odb_cells:
26
+ cell_name = cell.getName()
27
+ inout_pins = []
28
+ input_pins = []
29
+ output_pins = []
30
+ for mterm in cell.getMTerms():
31
+ if mterm.getSigType() in ["GROUND", "POWER", "ANALOG"]:
32
+ continue
33
+ pin_name = mterm.getName()
34
+ diff_area = mterm.getDiffArea()
35
+ gate_area = (
36
+ mterm.getDefaultAntennaModel()
37
+ and mterm.getDefaultAntennaModel().getGateArea()
38
+ or []
39
+ )
40
+ io_type = mterm.getIoType()
41
+ if io_type == "INOUT" and not (len(diff_area) or len(gate_area)):
42
+ inout_pins.append(pin_name)
43
+ elif io_type == "INPUT" and not len(gate_area):
44
+ input_pins.append(pin_name)
45
+ elif io_type == "OUTPUT" and not len(diff_area):
46
+ output_pins.append(pin_name)
47
+ if inout_pins:
48
+ print(
49
+ f"[WARNING] Cell '{cell_name}' has ({len(inout_pins)}) inout pin(s) without anetnna gate information not antenna diffusion information. They might be disconnected."
50
+ )
51
+ if input_pins:
52
+ print(
53
+ f"[WARNING] Cell '{cell_name}' has ({len(input_pins)}) input pin(s) without antenna gate information. They might not be connected to a gate."
54
+ )
55
+ if output_pins:
56
+ print(
57
+ f"[WARNING] Cell '{cell_name}' has ({len(output_pins)}) output pin(s) without antenna diffusion information. They might not be driven."
58
+ )
59
+
60
+ entry = {
61
+ "cell": cell_name,
62
+ "inout": inout_pins,
63
+ "output": output_pins,
64
+ "input": input_pins,
65
+ }
66
+ report.append(entry)
67
+
68
+ return report
69
+
70
+
71
+ def get_top_level_cell(input_lefs, design_lef, cell_name):
72
+ db = odb.dbDatabase.create()
73
+ for lef in input_lefs:
74
+ odb.read_lef(db, lef)
75
+ odb.read_lef(db, design_lef)
76
+
77
+ with NamedTemporaryFile("w") as f:
78
+ lines = dedent(
79
+ """VERSION 5.8 ;
80
+ DESIGN empty ;
81
+ END DESIGN
82
+ """
83
+ )
84
+ f.writelines(lines)
85
+ f.seek(0)
86
+ odb.read_def(db.getTech(), f.name)
87
+ libs = db.getLibs()
88
+ cells = {}
89
+ for lib in libs:
90
+ cells.update({m: m for m in lib.getMasters()})
91
+ top_level_cell = next(
92
+ filter(lambda cell: cell.getName() in cell_name, cells.keys())
93
+ )
94
+ return top_level_cell
95
+
96
+
97
+ @click.option(
98
+ "-c", "--cell-name", required=True, multiple=True, help="Names of cells to check"
99
+ )
100
+ @click.option("--design-lef", help="Top level design LEF view")
101
+ @click.option("-r", "--report-file", help="YAML report file")
102
+ @click.command()
103
+ @click_odb
104
+ def check_antenna_properties(reader, cell_name, report_file, input_lefs, design_lef):
105
+ cells = []
106
+ if design_lef:
107
+ cells.append(get_top_level_cell(input_lefs, design_lef, cell_name))
108
+ cells += list(filter(lambda cell: cell.getName() in cell_name, reader.cells))
109
+ report = check_cells(cells)
110
+
111
+ with open(report_file, "w") as f:
112
+ f.write(yaml.dump(report))
113
+
114
+
115
+ if __name__ == "__main__":
116
+ check_antenna_properties()
@@ -0,0 +1,109 @@
1
+ # Copyright 2020-2022 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import odb
15
+
16
+ from reader import OdbReader, click_odb, click
17
+
18
+
19
+ @click.command()
20
+ @click.option(
21
+ "-D",
22
+ "--top-def",
23
+ required=True,
24
+ help="DEF view of the top-level design instantiating the macro",
25
+ )
26
+ @click.option(
27
+ "-L",
28
+ "--top-lef",
29
+ required=True,
30
+ help="DEF view of the top-level design instantiating the macro",
31
+ )
32
+ @click.option("--keep-inner-connections", default=False, is_flag=True)
33
+ @click_odb
34
+ def contextualize(reader, top_def, top_lef, keep_inner_connections):
35
+ reader.add_lef(top_lef)
36
+
37
+ top = OdbReader(top_lef, top_def)
38
+ macro = reader
39
+
40
+ print("Block design name:", macro.name)
41
+ print("Top-level design name:", top.name)
42
+
43
+ nets_top = top.block.getNets()
44
+ to_connect = {}
45
+ MACRO_TOP_PLACEMENT_X = 0
46
+ MACRO_TOP_PLACEMENT_Y = 0
47
+
48
+ assert macro.name in [
49
+ inst.getMaster().getName() for inst in top.block.getInsts()
50
+ ], "%s not found in %s" % (macro.name, top.name)
51
+
52
+ for net in nets_top:
53
+ iterms = net.getITerms() # asssumption: no pins (bterms) on top level
54
+ block_net_name = None
55
+ for iterm in iterms:
56
+ macro_name = iterm.getMTerm().getMaster().getName()
57
+ if macro_name == macro.name:
58
+ block_net_name = iterm.getMTerm().getName()
59
+ macro_top_inst = iterm.getInst()
60
+ (
61
+ MACRO_TOP_PLACEMENT_X,
62
+ MACRO_TOP_PLACEMENT_Y,
63
+ ) = macro_top_inst.getLocation()
64
+ print("Block net name: ", block_net_name)
65
+ break
66
+ if block_net_name is not None:
67
+ to_connect[block_net_name] = []
68
+ for iterm in iterms:
69
+ macro_name = iterm.getMTerm().getMaster().getName()
70
+ if macro_name != macro.name:
71
+ to_connect[block_net_name].append(iterm)
72
+ block_net_name = None
73
+
74
+ # print(macro_name, inst_name, end= ' ')
75
+ # print(iterm.getMTerm().getName())
76
+
77
+ # print(to_connect)
78
+
79
+ nets_macro = macro.block.getNets()
80
+ created_macros = {}
81
+ for net in nets_macro:
82
+ iterms = net.getITerms() # asssumption: no pins (bterms) on top level
83
+ if not keep_inner_connections:
84
+ for iterm in iterms:
85
+ iterm.disconnect()
86
+ if net.getName() in to_connect:
87
+ for node_iterm in to_connect[net.getName()]:
88
+ node_master = node_iterm.getMTerm().getMaster()
89
+ node_inst = node_iterm.getInst()
90
+ node_inst_name = node_iterm.getInst().getName()
91
+ if node_inst_name not in created_macros:
92
+ created_macros[node_inst_name] = 1
93
+ print("Creating: ", node_master.getName(), node_inst_name)
94
+ new_inst = odb.dbInst_create(
95
+ macro.block, node_master, node_inst_name
96
+ )
97
+ new_inst.setOrient(node_inst.getOrient())
98
+ new_inst.setLocation(
99
+ node_inst.getLocation()[0] - MACRO_TOP_PLACEMENT_X,
100
+ node_inst.getLocation()[1] - MACRO_TOP_PLACEMENT_Y,
101
+ )
102
+ new_inst.setPlacementStatus("FIRM")
103
+ else:
104
+ new_inst = macro.block.findInst(node_inst_name)
105
+ new_inst.findITerm(node_iterm.getMTerm().getName()).connect(net)
106
+
107
+
108
+ if __name__ == "__main__":
109
+ contextualize()