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,84 @@
1
+ # Copyright 2020-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 json
15
+
16
+ import click
17
+
18
+ from ys_common import ys
19
+
20
+
21
+ @click.command()
22
+ @click.option("--output", type=click.Path(exists=False, dir_okay=False), required=True)
23
+ @click.option(
24
+ "--config-in", type=click.Path(exists=True, dir_okay=False), required=True
25
+ )
26
+ @click.option("--extra-in", type=click.Path(exists=True, dir_okay=False), required=True)
27
+ def json_header(
28
+ output,
29
+ config_in,
30
+ extra_in,
31
+ ):
32
+ config = json.load(open(config_in))
33
+ extra = json.load(open(extra_in))
34
+
35
+ blackbox_models = extra["blackbox_models"]
36
+
37
+ includes = config["VERILOG_INCLUDE_DIRS"] or []
38
+ defines = (
39
+ (config["VERILOG_DEFINES"] or [])
40
+ + [
41
+ f"PDK_{config['PDK']}",
42
+ f"SCL_{config['STD_CELL_LIBRARY']}",
43
+ "__librelane__",
44
+ "__pnr__",
45
+ ]
46
+ + (
47
+ []
48
+ if config.get("VERILOG_POWER_DEFINE") is None
49
+ else [config.get("VERILOG_POWER_DEFINE")]
50
+ )
51
+ )
52
+
53
+ d = ys.Design()
54
+ d.add_blackbox_models(
55
+ blackbox_models,
56
+ includes=includes,
57
+ defines=defines,
58
+ )
59
+ d.read_verilog_files(
60
+ config["VERILOG_FILES"],
61
+ top=config["DESIGN_NAME"],
62
+ synth_parameters=config["SYNTH_PARAMETERS"] or [],
63
+ includes=includes,
64
+ defines=defines,
65
+ use_synlig=config["USE_SYNLIG"],
66
+ synlig_defer=config["SYNLIG_DEFER"],
67
+ )
68
+ d.run_pass(
69
+ "hierarchy",
70
+ "-check",
71
+ "-top",
72
+ config["DESIGN_NAME"],
73
+ "-nokeep_prints",
74
+ "-nokeep_asserts",
75
+ )
76
+ d.run_pass("rename", "-top", config["DESIGN_NAME"])
77
+ d.run_pass("proc")
78
+ d.run_pass("flatten")
79
+ d.run_pass("opt_clean", "-purge")
80
+ d.run_pass("json", "-o", output)
81
+
82
+
83
+ if __name__ == "__main__":
84
+ json_header()
@@ -0,0 +1,493 @@
1
+ # Copyright 2020-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
+
15
+ # Parts of this file adapted from:
16
+ #
17
+ # * https://github.com/YosysHQ/yosys/blob/master/techlibs/common/synth.cc
18
+ # * https://github.com/YosysHQ/yosys/blob/master/passes/opt/opt.cc
19
+ #
20
+ # Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
21
+ #
22
+ # Permission to use, copy, modify, and/or distribute this software for any
23
+ # purpose with or without fee is hereby granted, provided that the above
24
+ # copyright notice and this permission notice appear in all copies.
25
+ #
26
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33
+
34
+ import os
35
+ import json
36
+ import shutil
37
+
38
+ import click
39
+
40
+ from ys_common import ys
41
+ from construct_abc_script import ABCScriptCreator
42
+
43
+
44
+ def librelane_proc(d: ys.Design, report_dir: str):
45
+ d.run_pass("proc_clean") # Clean up unused procedures
46
+ d.run_pass("proc_rmdead") # Remove dead procedures
47
+ d.run_pass("proc_prune") # Prune unused parts of procedures
48
+ d.run_pass("proc_init") # Initialize procedures
49
+ d.run_pass("proc_arst") # Analyze reset signals in procedures
50
+ d.run_pass("proc_rom") # Map ROMs within procedures
51
+ d.run_pass("proc_mux") # Optimize multiplexers within procedures
52
+ d.tee(
53
+ "proc_dlatch", o=os.path.join(report_dir, "latch.rpt")
54
+ ) # Report latches after procedure processing
55
+ d.run_pass("proc_dff") # Analyze flip-flops within procedures
56
+ d.run_pass("proc_memwr") # Analyze memory writes within procedures
57
+ d.run_pass("proc_clean") # Clean up after procedure processing
58
+ d.tee("check", o=os.path.join(report_dir, "pre_synth_chk.rpt"))
59
+ d.run_pass("opt_expr") # Optimize expressions
60
+
61
+
62
+ def librelane_opt(
63
+ d,
64
+ fast=False,
65
+ mux_undef=False,
66
+ mux_bool=False,
67
+ undriven=False,
68
+ fine=False,
69
+ purge=False,
70
+ noclkinv=False,
71
+ keepdc=False,
72
+ share_all=False,
73
+ nodffe=False,
74
+ nosdff=False,
75
+ sat=False,
76
+ opt_share=False,
77
+ noff=False,
78
+ ):
79
+ expr_args = []
80
+ merge_args = []
81
+ reduce_args = []
82
+ clean_args = []
83
+ dff_args = []
84
+ if purge:
85
+ clean_args.append("-purge")
86
+ if mux_undef:
87
+ expr_args.append("-mux_undef")
88
+ if mux_bool:
89
+ expr_args.append("-mux_bool")
90
+ if undriven:
91
+ expr_args.append("-undriven")
92
+ if fine:
93
+ expr_args.append("-fine")
94
+ reduce_args.append("-fine")
95
+ if noclkinv:
96
+ expr_args.append("-noclkinv")
97
+ if keepdc:
98
+ expr_args.append("-keepdc")
99
+ dff_args.append("-keepdc")
100
+ merge_args.append("-keepdc")
101
+ if nodffe:
102
+ dff_args.append("-nodffe")
103
+ if nosdff:
104
+ dff_args.append("-nosdff")
105
+ if sat:
106
+ dff_args.append("-sat")
107
+ if share_all:
108
+ merge_args.append("-share_all")
109
+ if fast:
110
+ while True:
111
+ d.run_pass("opt_expr", *expr_args)
112
+ d.run_pass("opt_merge", *merge_args)
113
+ d.scratchpad_unset("opt.did_something")
114
+ if not noff:
115
+ d.run_pass("opt_dff", *dff_args)
116
+ if not d.scratchpad_get_bool("opt.did_something"):
117
+ break
118
+ d.run_pass("opt_clean", *clean_args)
119
+ ys.log_header(d, "Rerunning OPT passes (Removed registers in this run.)")
120
+ d.run_pass("opt_clean", *clean_args)
121
+ else:
122
+ d.run_pass("opt_expr", *expr_args)
123
+ d.run_pass("opt_merge", "-nomux", *merge_args)
124
+ while True:
125
+ d.scratchpad_unset("opt.did_something")
126
+ d.run_pass("opt_muxtree")
127
+ d.run_pass("opt_reduce", *reduce_args)
128
+ d.run_pass("opt_merge", *merge_args)
129
+ if opt_share:
130
+ d.run_pass("opt_share")
131
+ if not noff:
132
+ d.run_pass("opt_dff", *dff_args)
133
+ d.run_pass("opt_clean", *clean_args)
134
+ d.run_pass("opt_expr", *expr_args)
135
+ if not d.scratchpad_get_bool("opt.did_something"):
136
+ break
137
+ ys.log_header(d, "Rerunning OPT passes. (Maybe there is more to do…)")
138
+
139
+ d.optimize()
140
+ d.sort()
141
+ d.check()
142
+
143
+
144
+ def librelane_synth(
145
+ d, top, flatten, report_dir, *, booth=False, abc_dff=False, undriven=True
146
+ ):
147
+ d.run_pass("hierarchy", "-check", "-top", top, "-nokeep_prints", "-nokeep_asserts")
148
+ librelane_proc(d, report_dir)
149
+
150
+ if flatten:
151
+ d.run_pass("flatten") # Flatten the design hierarchy
152
+
153
+ d.run_pass("opt_expr") # Optimize expressions again
154
+
155
+ d.run_pass("opt_clean") # Clean up after optimization
156
+
157
+ # Perform various logic optimization passes
158
+ librelane_opt(d, nodffe=True, nosdff=True)
159
+ d.run_pass("fsm") # Identify and optimize finite state machines
160
+ librelane_opt(d)
161
+ d.run_pass("wreduce") # Reduce logic using algebraic rewriting
162
+ d.run_pass("peepopt") # Perform local peephole optimization
163
+ d.run_pass("opt_clean") # Clean up after optimization
164
+ if booth:
165
+ d.run_pass("booth")
166
+ d.run_pass("alumacc") # Optimize arithmetic logic unitsb
167
+ d.run_pass("share") # Share logic across the design
168
+ librelane_opt(d)
169
+
170
+ # Memory optimization
171
+ d.run_pass("memory", "-nomap") # Analyze memories but don't map them yet
172
+ d.run_pass("opt_clean") # Clean up after memory analysis
173
+
174
+ # Perform more aggressive optimization with faster runtime
175
+ librelane_opt(
176
+ d,
177
+ fast=True,
178
+ opt_share=True, # affects opt_share
179
+ mux_undef=True, # affects opt_expr
180
+ mux_bool=True, # affects opt_expr
181
+ undriven=undriven, # affects opt_expr
182
+ fine=True, # affects opt_expr, opt_reduce
183
+ )
184
+
185
+ # Technology mapping
186
+ d.run_pass("memory_map") # Map memories to standard cells
187
+ librelane_opt(
188
+ d,
189
+ opt_share=True, # affects opt_share
190
+ mux_undef=True, # affects opt_expr
191
+ mux_bool=True, # affects opt_expr
192
+ undriven=undriven, # affects opt_expr
193
+ fine=True, # affects opt_expr, opt_reduce
194
+ )
195
+ d.run_pass("techmap")
196
+
197
+ # Couple more fast opt iterations
198
+ librelane_opt(d, fast=True)
199
+ librelane_opt(d, fast=True)
200
+
201
+ d.run_pass(
202
+ "abc", "-fast", *(["-dff"] if abc_dff else [])
203
+ ) # Run ABC with fast settings
204
+ d.run_pass("opt", "-fast") # MORE fast optimization
205
+
206
+ # Checks and Stats
207
+ d.run_pass("hierarchy", "-check", "-top", top, "-nokeep_prints", "-nokeep_asserts")
208
+ d.run_pass("check")
209
+ d.run_pass("stat")
210
+
211
+
212
+ @click.command()
213
+ @click.option("--output", type=click.Path(exists=False, dir_okay=False), required=True)
214
+ @click.option("--config-in", type=click.Path(exists=True), required=True)
215
+ @click.option("--extra-in", type=click.Path(exists=True), required=True)
216
+ @click.option("--lighter-dff-map", type=click.Path(exists=True), required=False)
217
+ @click.argument("inputs", nargs=-1)
218
+ def synthesize(
219
+ output,
220
+ config_in,
221
+ extra_in,
222
+ lighter_dff_map,
223
+ inputs,
224
+ ):
225
+ config = json.load(open(config_in))
226
+ extra = json.load(open(extra_in))
227
+
228
+ includes = config.get("VERILOG_INCLUDE_DIRS") or []
229
+ defines = (config.get("VERILOG_DEFINES") or []) + [
230
+ f"PDK_{config['PDK']}",
231
+ f"SCL_{config['STD_CELL_LIBRARY']}",
232
+ "__librelane__",
233
+ "__pnr__",
234
+ ]
235
+
236
+ blackbox_models = extra["blackbox_models"]
237
+ libs = extra["libs_synth"]
238
+
239
+ d = ys.Design()
240
+
241
+ step_dir = os.path.dirname(output)
242
+ report_dir = os.path.join(step_dir, "reports")
243
+ os.makedirs(report_dir, exist_ok=True)
244
+
245
+ d.add_blackbox_models(blackbox_models, includes=includes, defines=defines)
246
+
247
+ clock_period = config["CLOCK_PERIOD"] * 1000 # ns -> ps
248
+
249
+ # ABC only supports these two:
250
+ # https://github.com/YosysHQ/abc/blob/28d955ca97a1c4be3aed4062aec0241a734fac5d/src/map/scl/sclUtil.c#L257
251
+ sdc_path = os.path.join(step_dir, "synthesis.abc.sdc")
252
+ with open(sdc_path, "w") as f:
253
+ print(f"set_driving_cell {config['SYNTH_DRIVING_CELL']}", file=f)
254
+ print(f"set_load {config['OUTPUT_CAP_LOAD']}", file=f)
255
+
256
+ ys.log(f"[INFO] Using SDC file '{sdc_path}' for ABC…")
257
+
258
+ if len(inputs):
259
+ d.read_verilog_files(
260
+ inputs,
261
+ top=config["DESIGN_NAME"],
262
+ synth_parameters=[],
263
+ includes=includes,
264
+ defines=defines,
265
+ use_synlig=False,
266
+ synlig_defer=False,
267
+ )
268
+ elif verilog_files := config.get("VERILOG_FILES"):
269
+ d.read_verilog_files(
270
+ verilog_files,
271
+ top=config["DESIGN_NAME"],
272
+ synth_parameters=config["SYNTH_PARAMETERS"] or [],
273
+ includes=includes,
274
+ defines=defines,
275
+ use_synlig=config["USE_SYNLIG"],
276
+ synlig_defer=config["SYNLIG_DEFER"],
277
+ )
278
+ elif vhdl_files := config.get("VHDL_FILES"):
279
+ d.run_pass("plugin", "-i", "ghdl")
280
+ d.run_pass("ghdl", *vhdl_files, "-e", config["DESIGN_NAME"])
281
+ else:
282
+ ys.log_error(
283
+ "Script called inappropriately: config must include either VERILOG_FILES or VHDL_FILES.",
284
+ )
285
+ exit(1)
286
+
287
+ d.run_pass(
288
+ "hierarchy",
289
+ "-check",
290
+ "-top",
291
+ config["DESIGN_NAME"],
292
+ "-nokeep_prints",
293
+ "-nokeep_asserts",
294
+ )
295
+ d.run_pass("rename", "-top", config["DESIGN_NAME"])
296
+ d.run_pass("select", "-module", config["DESIGN_NAME"])
297
+ try:
298
+ d.run_pass(
299
+ "show", "-format", "dot", "-prefix", os.path.join(step_dir, "hierarchy")
300
+ )
301
+ except Exception:
302
+ pass
303
+ d.run_pass("select", "-clear")
304
+
305
+ lib_arguments = []
306
+ for lib in libs:
307
+ lib_arguments.extend(["-liberty", lib])
308
+
309
+ if config["SYNTH_ELABORATE_ONLY"]:
310
+ librelane_proc(d, report_dir)
311
+ if config["SYNTH_ELABORATE_FLATTEN"]:
312
+ d.run_pass("flatten", "-noscopeinfo")
313
+ d.run_pass("setattr", "-set", "keep", "1")
314
+ d.run_pass("splitnets")
315
+ d.run_pass("opt_clean", "-purge")
316
+ d.tee("check", o=os.path.join(report_dir, "chk.rpt"))
317
+ d.tee("stat", "-json", *lib_arguments, o=os.path.join(report_dir, "stat.json"))
318
+ d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "stat.rpt"))
319
+
320
+ noattr_flag = []
321
+ if config["SYNTH_WRITE_NOATTR"]:
322
+ noattr_flag.append("-noattr")
323
+
324
+ d.run_pass(
325
+ "write_verilog",
326
+ *noattr_flag,
327
+ "-nohex",
328
+ "-nodec",
329
+ "-defparam",
330
+ output,
331
+ )
332
+ d.run_pass("write_json", f"{output}.json")
333
+ exit(0)
334
+
335
+ if config["SYNTH_TRISTATE_MAP"] is not None:
336
+ d.run_pass("tribuf")
337
+
338
+ adder_type = config["SYNTH_ADDER_TYPE"]
339
+ if adder_type not in ["YOSYS", "FA"]:
340
+ if mapping := config[f"SYNTH_{adder_type}_MAP"]:
341
+ ys.log(f"[INFO] Applying {adder_type} mapping from '{mapping}'…")
342
+ d.run_pass("techmap", "-map", mapping)
343
+
344
+ if mapping := lighter_dff_map:
345
+ ys.log(f"[INFO] Using Lighter with mapping '{mapping}'…")
346
+ d.run_pass("plugin", "-i", "lighter")
347
+ d.run_pass("reg_clock_gating", "-map", mapping)
348
+
349
+ librelane_synth(
350
+ d,
351
+ config["DESIGN_NAME"],
352
+ config["SYNTH_HIERARCHY_MODE"] == "flatten",
353
+ report_dir,
354
+ booth=config["SYNTH_MUL_BOOTH"],
355
+ abc_dff=config["SYNTH_ABC_DFF"],
356
+ undriven=config.get("SYNTH_TIE_UNDEFINED") is not None,
357
+ )
358
+
359
+ d.run_pass("delete", "t:$print")
360
+ d.run_pass("delete", "t:$assert")
361
+
362
+ try:
363
+ d.run_pass(
364
+ "show",
365
+ "-format",
366
+ "dot",
367
+ "-prefix",
368
+ os.path.join(step_dir, "primitive_techmap"),
369
+ )
370
+ except Exception:
371
+ pass
372
+
373
+ d.run_pass("opt")
374
+ d.run_pass("opt_clean", "-purge")
375
+
376
+ d.tee(
377
+ "stat", "-json", *lib_arguments, o=os.path.join(report_dir, "pre_techmap.json")
378
+ )
379
+ d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "pre_techmap.rpt"))
380
+
381
+ if tristate_mapping := config["SYNTH_TRISTATE_MAP"]:
382
+ ys.log(f"[INFO] Applying tri-state buffer mapping from '{tristate_mapping}'…")
383
+ d.run_pass("techmap", "-map", tristate_mapping)
384
+ d.run_pass("simplemap")
385
+ if fa_mapping := config["SYNTH_FA_MAP"]:
386
+ if adder_type == "FA":
387
+ ys.log(f"[INFO] Applying full-adder mapping from '{fa_mapping}'…")
388
+ d.run_pass("techmap", "-map", fa_mapping)
389
+ if latch_mapping := config["SYNTH_LATCH_MAP"]:
390
+ ys.log(f"[INFO] Applying latch mapping from '{latch_mapping}'…")
391
+ d.run_pass("techmap", "-map", latch_mapping)
392
+ d.run_pass("simplemap")
393
+ if extra_mapping := config["SYNTH_EXTRA_MAPPING_FILE"]:
394
+ ys.log(f"[INFO] Applying extra mappings from '{extra_mapping}'…")
395
+ d.run_pass("techmap", "-map", extra_mapping)
396
+
397
+ dfflibmap_args = []
398
+ for lib in libs:
399
+ dfflibmap_args.extend(["-liberty", lib])
400
+ d.run_pass("dfflibmap", *dfflibmap_args)
401
+
402
+ d.tee("stat", "-json", *lib_arguments, o=os.path.join(report_dir, "post_dff.json"))
403
+ d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "post_dff.rpt"))
404
+
405
+ script_creator = ABCScriptCreator(config)
406
+
407
+ def run_strategy(d):
408
+ abc_script = script_creator.generate_abc_script(
409
+ step_dir,
410
+ config["SYNTH_STRATEGY"],
411
+ )
412
+ ys.log(f"[INFO] Using generated ABC script '{abc_script}'…")
413
+ d.run_pass(
414
+ "abc",
415
+ "-script",
416
+ abc_script,
417
+ "-D",
418
+ f"{clock_period}",
419
+ "-constr",
420
+ sdc_path,
421
+ "-showtmp",
422
+ *lib_arguments,
423
+ *(["-dff"] if config["SYNTH_ABC_DFF"] else []),
424
+ )
425
+
426
+ if value := config.get("SYNTH_TIE_UNDEFINED"):
427
+ flag = "-zero" if value == "low" else "-one"
428
+ d.run_pass("setundef", flag)
429
+
430
+ d.run_pass(
431
+ "hilomap",
432
+ "-hicell",
433
+ *config["SYNTH_TIEHI_CELL"].split("/"),
434
+ "-locell",
435
+ *config["SYNTH_TIELO_CELL"].split("/"),
436
+ )
437
+
438
+ if config["SYNTH_SPLITNETS"]:
439
+ d.run_pass("splitnets")
440
+ d.run_pass("opt_clean", "-purge")
441
+
442
+ if config["SYNTH_DIRECT_WIRE_BUFFERING"]:
443
+ d.run_pass("insbuf", "-buf", *config["SYNTH_BUFFER_CELL"].split("/"))
444
+
445
+ d.tee("check", o=os.path.join(report_dir, "chk.rpt"))
446
+ d.tee("stat", "-json", *lib_arguments, o=os.path.join(report_dir, "stat.json"))
447
+ d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "stat.rpt"))
448
+
449
+ if config["SYNTH_AUTONAME"]:
450
+ # Generate public names for the various nets, resulting in very long
451
+ # names that include the full hierarchy, which is preferable to the
452
+ # internal names that are simply sequential numbers such as `_000019_`.
453
+ # Renamed net names can be very long, such as:
454
+ # manual_reset_gf180mcu_fd_sc_mcu7t5v0__dffq_1_Q_D_gf180mcu_ \
455
+ # fd_sc_mcu7t5v0__nor3_1_ZN_A1_gf180mcu_fd_sc_mcu7t5v0__aoi21_ \
456
+ # 1_A2_A1_gf180mcu_fd_sc_mcu7t5v0__nand3_1_ZN_A3_gf180mcu_fd_ \
457
+ # sc_mcu7t5v0__and3_1_A3_Z_gf180mcu_fd_sc_mcu7t5v0__buf_1_I_Z
458
+ d.run_pass("autoname")
459
+
460
+ noattr_flag = []
461
+ if config["SYNTH_WRITE_NOATTR"]:
462
+ noattr_flag.append("-noattr")
463
+
464
+ d.run_pass(
465
+ "write_verilog",
466
+ *noattr_flag,
467
+ "-noexpr",
468
+ "-nohex",
469
+ "-nodec",
470
+ "-defparam",
471
+ output,
472
+ )
473
+ d.run_pass("write_json", f"{output}.json")
474
+
475
+ run_strategy(d)
476
+
477
+ if config["SYNTH_HIERARCHY_MODE"] == "deferred_flatten":
478
+ # Resynthesize, flattening
479
+ d_flat = ys.Design()
480
+ d_flat.add_blackbox_models(blackbox_models, includes=includes, defines=defines)
481
+
482
+ shutil.copy(output, f"{output}.hierarchy.nl.v")
483
+ d_flat.run_pass("read_verilog", "-sv", output)
484
+ d_flat.run_pass(
485
+ "synth",
486
+ "-flatten",
487
+ *(["-booth"] if config["SYNTH_MUL_BOOTH"] else []),
488
+ )
489
+ run_strategy(d_flat)
490
+
491
+
492
+ if __name__ == "__main__":
493
+ synthesize()