siliconcompiler 0.26.5__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.
Files changed (251) hide show
  1. siliconcompiler/__init__.py +24 -0
  2. siliconcompiler/__main__.py +12 -0
  3. siliconcompiler/_common.py +49 -0
  4. siliconcompiler/_metadata.py +36 -0
  5. siliconcompiler/apps/__init__.py +0 -0
  6. siliconcompiler/apps/_common.py +76 -0
  7. siliconcompiler/apps/sc.py +92 -0
  8. siliconcompiler/apps/sc_dashboard.py +94 -0
  9. siliconcompiler/apps/sc_issue.py +178 -0
  10. siliconcompiler/apps/sc_remote.py +199 -0
  11. siliconcompiler/apps/sc_server.py +39 -0
  12. siliconcompiler/apps/sc_show.py +142 -0
  13. siliconcompiler/apps/smake.py +232 -0
  14. siliconcompiler/checklists/__init__.py +0 -0
  15. siliconcompiler/checklists/oh_tapeout.py +41 -0
  16. siliconcompiler/core.py +3221 -0
  17. siliconcompiler/data/RobotoMono/LICENSE.txt +202 -0
  18. siliconcompiler/data/RobotoMono/RobotoMono-Regular.ttf +0 -0
  19. siliconcompiler/data/heartbeat.v +18 -0
  20. siliconcompiler/data/logo.png +0 -0
  21. siliconcompiler/flowgraph.py +570 -0
  22. siliconcompiler/flows/__init__.py +0 -0
  23. siliconcompiler/flows/_common.py +67 -0
  24. siliconcompiler/flows/asicflow.py +180 -0
  25. siliconcompiler/flows/asictopflow.py +38 -0
  26. siliconcompiler/flows/dvflow.py +86 -0
  27. siliconcompiler/flows/fpgaflow.py +202 -0
  28. siliconcompiler/flows/generate_openroad_rcx.py +66 -0
  29. siliconcompiler/flows/lintflow.py +35 -0
  30. siliconcompiler/flows/screenshotflow.py +51 -0
  31. siliconcompiler/flows/showflow.py +59 -0
  32. siliconcompiler/flows/signoffflow.py +53 -0
  33. siliconcompiler/flows/synflow.py +128 -0
  34. siliconcompiler/fpgas/__init__.py +0 -0
  35. siliconcompiler/fpgas/lattice_ice40.py +42 -0
  36. siliconcompiler/fpgas/vpr_example.py +109 -0
  37. siliconcompiler/issue.py +300 -0
  38. siliconcompiler/libs/__init__.py +0 -0
  39. siliconcompiler/libs/asap7sc7p5t.py +8 -0
  40. siliconcompiler/libs/gf180mcu.py +8 -0
  41. siliconcompiler/libs/nangate45.py +8 -0
  42. siliconcompiler/libs/sky130hd.py +8 -0
  43. siliconcompiler/libs/sky130io.py +8 -0
  44. siliconcompiler/package.py +412 -0
  45. siliconcompiler/pdks/__init__.py +0 -0
  46. siliconcompiler/pdks/asap7.py +8 -0
  47. siliconcompiler/pdks/freepdk45.py +8 -0
  48. siliconcompiler/pdks/gf180.py +8 -0
  49. siliconcompiler/pdks/skywater130.py +8 -0
  50. siliconcompiler/remote/__init__.py +36 -0
  51. siliconcompiler/remote/client.py +891 -0
  52. siliconcompiler/remote/schema.py +106 -0
  53. siliconcompiler/remote/server.py +507 -0
  54. siliconcompiler/remote/server_schema/requests/cancel_job.json +51 -0
  55. siliconcompiler/remote/server_schema/requests/check_progress.json +61 -0
  56. siliconcompiler/remote/server_schema/requests/check_server.json +38 -0
  57. siliconcompiler/remote/server_schema/requests/delete_job.json +51 -0
  58. siliconcompiler/remote/server_schema/requests/get_results.json +48 -0
  59. siliconcompiler/remote/server_schema/requests/remote_run.json +40 -0
  60. siliconcompiler/remote/server_schema/responses/cancel_job.json +18 -0
  61. siliconcompiler/remote/server_schema/responses/check_progress.json +30 -0
  62. siliconcompiler/remote/server_schema/responses/check_server.json +32 -0
  63. siliconcompiler/remote/server_schema/responses/delete_job.json +18 -0
  64. siliconcompiler/remote/server_schema/responses/get_results.json +21 -0
  65. siliconcompiler/remote/server_schema/responses/remote_run.json +25 -0
  66. siliconcompiler/report/__init__.py +13 -0
  67. siliconcompiler/report/html_report.py +74 -0
  68. siliconcompiler/report/report.py +355 -0
  69. siliconcompiler/report/streamlit_report.py +137 -0
  70. siliconcompiler/report/streamlit_viewer.py +944 -0
  71. siliconcompiler/report/summary_image.py +117 -0
  72. siliconcompiler/report/summary_table.py +105 -0
  73. siliconcompiler/report/utils.py +163 -0
  74. siliconcompiler/scheduler/__init__.py +2092 -0
  75. siliconcompiler/scheduler/docker_runner.py +253 -0
  76. siliconcompiler/scheduler/run_node.py +138 -0
  77. siliconcompiler/scheduler/send_messages.py +178 -0
  78. siliconcompiler/scheduler/slurm.py +208 -0
  79. siliconcompiler/scheduler/validation/email_credentials.json +54 -0
  80. siliconcompiler/schema/__init__.py +7 -0
  81. siliconcompiler/schema/schema_cfg.py +4014 -0
  82. siliconcompiler/schema/schema_obj.py +1841 -0
  83. siliconcompiler/schema/utils.py +93 -0
  84. siliconcompiler/sphinx_ext/__init__.py +0 -0
  85. siliconcompiler/sphinx_ext/dynamicgen.py +1006 -0
  86. siliconcompiler/sphinx_ext/schemagen.py +221 -0
  87. siliconcompiler/sphinx_ext/utils.py +166 -0
  88. siliconcompiler/targets/__init__.py +0 -0
  89. siliconcompiler/targets/asap7_demo.py +68 -0
  90. siliconcompiler/targets/asic_demo.py +38 -0
  91. siliconcompiler/targets/fpgaflow_demo.py +47 -0
  92. siliconcompiler/targets/freepdk45_demo.py +59 -0
  93. siliconcompiler/targets/gf180_demo.py +77 -0
  94. siliconcompiler/targets/skywater130_demo.py +70 -0
  95. siliconcompiler/templates/email/general.j2 +66 -0
  96. siliconcompiler/templates/email/summary.j2 +43 -0
  97. siliconcompiler/templates/issue/README.txt +26 -0
  98. siliconcompiler/templates/issue/run.sh +6 -0
  99. siliconcompiler/templates/report/bootstrap.min.css +7 -0
  100. siliconcompiler/templates/report/bootstrap.min.js +7 -0
  101. siliconcompiler/templates/report/bootstrap_LICENSE.md +24 -0
  102. siliconcompiler/templates/report/sc_report.j2 +427 -0
  103. siliconcompiler/templates/slurm/run.sh +9 -0
  104. siliconcompiler/templates/tcl/manifest.tcl.j2 +137 -0
  105. siliconcompiler/tools/__init__.py +0 -0
  106. siliconcompiler/tools/_common/__init__.py +432 -0
  107. siliconcompiler/tools/_common/asic.py +115 -0
  108. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +76 -0
  109. siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +63 -0
  110. siliconcompiler/tools/bambu/bambu.py +32 -0
  111. siliconcompiler/tools/bambu/convert.py +77 -0
  112. siliconcompiler/tools/bluespec/bluespec.py +40 -0
  113. siliconcompiler/tools/bluespec/convert.py +103 -0
  114. siliconcompiler/tools/builtin/_common.py +155 -0
  115. siliconcompiler/tools/builtin/builtin.py +26 -0
  116. siliconcompiler/tools/builtin/concatenate.py +85 -0
  117. siliconcompiler/tools/builtin/join.py +27 -0
  118. siliconcompiler/tools/builtin/maximum.py +46 -0
  119. siliconcompiler/tools/builtin/minimum.py +57 -0
  120. siliconcompiler/tools/builtin/mux.py +70 -0
  121. siliconcompiler/tools/builtin/nop.py +38 -0
  122. siliconcompiler/tools/builtin/verify.py +83 -0
  123. siliconcompiler/tools/chisel/SCDriver.scala +10 -0
  124. siliconcompiler/tools/chisel/build.sbt +27 -0
  125. siliconcompiler/tools/chisel/chisel.py +37 -0
  126. siliconcompiler/tools/chisel/convert.py +140 -0
  127. siliconcompiler/tools/execute/exec_input.py +41 -0
  128. siliconcompiler/tools/execute/execute.py +17 -0
  129. siliconcompiler/tools/genfasm/bitstream.py +61 -0
  130. siliconcompiler/tools/genfasm/genfasm.py +40 -0
  131. siliconcompiler/tools/ghdl/convert.py +87 -0
  132. siliconcompiler/tools/ghdl/ghdl.py +41 -0
  133. siliconcompiler/tools/icarus/compile.py +87 -0
  134. siliconcompiler/tools/icarus/icarus.py +36 -0
  135. siliconcompiler/tools/icepack/bitstream.py +20 -0
  136. siliconcompiler/tools/icepack/icepack.py +43 -0
  137. siliconcompiler/tools/klayout/export.py +117 -0
  138. siliconcompiler/tools/klayout/klayout.py +119 -0
  139. siliconcompiler/tools/klayout/klayout_export.py +205 -0
  140. siliconcompiler/tools/klayout/klayout_operations.py +363 -0
  141. siliconcompiler/tools/klayout/klayout_show.py +242 -0
  142. siliconcompiler/tools/klayout/klayout_utils.py +176 -0
  143. siliconcompiler/tools/klayout/operations.py +194 -0
  144. siliconcompiler/tools/klayout/screenshot.py +98 -0
  145. siliconcompiler/tools/klayout/show.py +101 -0
  146. siliconcompiler/tools/magic/drc.py +49 -0
  147. siliconcompiler/tools/magic/extspice.py +19 -0
  148. siliconcompiler/tools/magic/magic.py +85 -0
  149. siliconcompiler/tools/magic/sc_drc.tcl +96 -0
  150. siliconcompiler/tools/magic/sc_extspice.tcl +54 -0
  151. siliconcompiler/tools/magic/sc_magic.tcl +47 -0
  152. siliconcompiler/tools/montage/montage.py +30 -0
  153. siliconcompiler/tools/montage/tile.py +66 -0
  154. siliconcompiler/tools/netgen/count_lvs.py +132 -0
  155. siliconcompiler/tools/netgen/lvs.py +90 -0
  156. siliconcompiler/tools/netgen/netgen.py +36 -0
  157. siliconcompiler/tools/netgen/sc_lvs.tcl +46 -0
  158. siliconcompiler/tools/nextpnr/apr.py +24 -0
  159. siliconcompiler/tools/nextpnr/nextpnr.py +59 -0
  160. siliconcompiler/tools/openfpgaloader/openfpgaloader.py +39 -0
  161. siliconcompiler/tools/openroad/__init__.py +0 -0
  162. siliconcompiler/tools/openroad/cts.py +45 -0
  163. siliconcompiler/tools/openroad/dfm.py +66 -0
  164. siliconcompiler/tools/openroad/export.py +131 -0
  165. siliconcompiler/tools/openroad/floorplan.py +70 -0
  166. siliconcompiler/tools/openroad/openroad.py +977 -0
  167. siliconcompiler/tools/openroad/physyn.py +27 -0
  168. siliconcompiler/tools/openroad/place.py +41 -0
  169. siliconcompiler/tools/openroad/rcx_bench.py +95 -0
  170. siliconcompiler/tools/openroad/rcx_extract.py +34 -0
  171. siliconcompiler/tools/openroad/route.py +45 -0
  172. siliconcompiler/tools/openroad/screenshot.py +60 -0
  173. siliconcompiler/tools/openroad/scripts/sc_apr.tcl +499 -0
  174. siliconcompiler/tools/openroad/scripts/sc_cts.tcl +64 -0
  175. siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +20 -0
  176. siliconcompiler/tools/openroad/scripts/sc_export.tcl +98 -0
  177. siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +413 -0
  178. siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +158 -0
  179. siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +7 -0
  180. siliconcompiler/tools/openroad/scripts/sc_place.tcl +84 -0
  181. siliconcompiler/tools/openroad/scripts/sc_procs.tcl +423 -0
  182. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +63 -0
  183. siliconcompiler/tools/openroad/scripts/sc_rcx_bench.tcl +20 -0
  184. siliconcompiler/tools/openroad/scripts/sc_rcx_extract.tcl +12 -0
  185. siliconcompiler/tools/openroad/scripts/sc_route.tcl +133 -0
  186. siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +21 -0
  187. siliconcompiler/tools/openroad/scripts/sc_write.tcl +5 -0
  188. siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +361 -0
  189. siliconcompiler/tools/openroad/show.py +94 -0
  190. siliconcompiler/tools/openroad/templates/pex.tcl +8 -0
  191. siliconcompiler/tools/opensta/__init__.py +101 -0
  192. siliconcompiler/tools/opensta/report_libraries.py +28 -0
  193. siliconcompiler/tools/opensta/scripts/sc_procs.tcl +47 -0
  194. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +74 -0
  195. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +268 -0
  196. siliconcompiler/tools/opensta/timing.py +214 -0
  197. siliconcompiler/tools/slang/__init__.py +49 -0
  198. siliconcompiler/tools/slang/lint.py +101 -0
  199. siliconcompiler/tools/surelog/__init__.py +123 -0
  200. siliconcompiler/tools/surelog/parse.py +183 -0
  201. siliconcompiler/tools/surelog/templates/output.v +7 -0
  202. siliconcompiler/tools/sv2v/convert.py +46 -0
  203. siliconcompiler/tools/sv2v/sv2v.py +37 -0
  204. siliconcompiler/tools/template/template.py +125 -0
  205. siliconcompiler/tools/verilator/compile.py +139 -0
  206. siliconcompiler/tools/verilator/lint.py +19 -0
  207. siliconcompiler/tools/verilator/parse.py +27 -0
  208. siliconcompiler/tools/verilator/verilator.py +172 -0
  209. siliconcompiler/tools/vivado/__init__.py +7 -0
  210. siliconcompiler/tools/vivado/bitstream.py +21 -0
  211. siliconcompiler/tools/vivado/place.py +21 -0
  212. siliconcompiler/tools/vivado/route.py +21 -0
  213. siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +6 -0
  214. siliconcompiler/tools/vivado/scripts/sc_place.tcl +2 -0
  215. siliconcompiler/tools/vivado/scripts/sc_route.tcl +4 -0
  216. siliconcompiler/tools/vivado/scripts/sc_run.tcl +45 -0
  217. siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +25 -0
  218. siliconcompiler/tools/vivado/syn_fpga.py +20 -0
  219. siliconcompiler/tools/vivado/vivado.py +147 -0
  220. siliconcompiler/tools/vpr/_json_constraint.py +63 -0
  221. siliconcompiler/tools/vpr/_xml_constraint.py +109 -0
  222. siliconcompiler/tools/vpr/place.py +137 -0
  223. siliconcompiler/tools/vpr/route.py +124 -0
  224. siliconcompiler/tools/vpr/screenshot.py +54 -0
  225. siliconcompiler/tools/vpr/show.py +88 -0
  226. siliconcompiler/tools/vpr/vpr.py +357 -0
  227. siliconcompiler/tools/xyce/xyce.py +36 -0
  228. siliconcompiler/tools/yosys/lec.py +56 -0
  229. siliconcompiler/tools/yosys/prepareLib.py +59 -0
  230. siliconcompiler/tools/yosys/sc_lec.tcl +84 -0
  231. siliconcompiler/tools/yosys/sc_syn.tcl +79 -0
  232. siliconcompiler/tools/yosys/syn_asic.py +565 -0
  233. siliconcompiler/tools/yosys/syn_asic.tcl +377 -0
  234. siliconcompiler/tools/yosys/syn_asic_fpga_shared.tcl +31 -0
  235. siliconcompiler/tools/yosys/syn_fpga.py +146 -0
  236. siliconcompiler/tools/yosys/syn_fpga.tcl +233 -0
  237. siliconcompiler/tools/yosys/syn_strategies.tcl +81 -0
  238. siliconcompiler/tools/yosys/techmaps/lcu_kogge_stone.v +39 -0
  239. siliconcompiler/tools/yosys/templates/abc.const +2 -0
  240. siliconcompiler/tools/yosys/yosys.py +147 -0
  241. siliconcompiler/units.py +259 -0
  242. siliconcompiler/use.py +177 -0
  243. siliconcompiler/utils/__init__.py +423 -0
  244. siliconcompiler/utils/asic.py +158 -0
  245. siliconcompiler/utils/showtools.py +25 -0
  246. siliconcompiler-0.26.5.dist-info/LICENSE +190 -0
  247. siliconcompiler-0.26.5.dist-info/METADATA +195 -0
  248. siliconcompiler-0.26.5.dist-info/RECORD +251 -0
  249. siliconcompiler-0.26.5.dist-info/WHEEL +5 -0
  250. siliconcompiler-0.26.5.dist-info/entry_points.txt +12 -0
  251. siliconcompiler-0.26.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,242 @@
1
+ import pya
2
+ import os
3
+ import sys
4
+
5
+
6
+ def show(schema, tech, input_path, output_path, screenshot=False):
7
+ # Extract info from manifest
8
+ flow = schema.get('option', 'flow')
9
+ step = schema.get('arg', 'step')
10
+ index = schema.get('arg', 'index')
11
+ task = schema.get('flowgraph', flow, step, index, 'task')
12
+
13
+ if 'hide_layers' in schema.getkeys('tool', 'klayout', 'task', task, 'var'):
14
+ sc_hide_layers = schema.get('tool', 'klayout', 'task', task, 'var', 'hide_layers',
15
+ step=step, index=index)
16
+ else:
17
+ sc_hide_layers = []
18
+
19
+ # Load KLayout technology file
20
+ layoutOptions = tech.load_layout_options
21
+
22
+ # These may be disabled in our KLayout tech file for reasons relating to GDS
23
+ # export, but for the purposes of viewing we'll hardcode them to True.
24
+ layoutOptions.lefdef_config.produce_blockages = True
25
+ layoutOptions.lefdef_config.produce_cell_outlines = True
26
+ layoutOptions.lefdef_config.produce_obstructions = True
27
+
28
+ # Always use LEF geometry even when LEF file contains FOREIGN statement.
29
+ layoutOptions.lefdef_config.macro_resolution_mode = 1
30
+
31
+ tech.load_layout_options = layoutOptions
32
+
33
+ app = pya.Application.instance()
34
+ main_window = pya.MainWindow.instance()
35
+ if not main_window:
36
+ print('[WARNING] unable to show layout as the main window is not available')
37
+ return
38
+
39
+ # Opinionated default KLayout configuration
40
+ # see ~/.klayout/klayoutrc for a list of configuration keys
41
+
42
+ # show all cells
43
+ app.set_config('full-hierarchy-new-cell', 'true')
44
+ # no tip pop-ups
45
+ app.set_config('tip-window-hidden', ','.join(['only-top-level-shown-by-default=3',
46
+ 'editor-mode=4',
47
+ 'editor-mode=0']))
48
+ # hide text
49
+ app.set_config('text-visible', 'false')
50
+ # dark background
51
+ app.set_config('background-color', '#212121')
52
+
53
+ # Display the file!
54
+ print(f"[INFO] Opening {input_path}")
55
+ cell_view = main_window.load_layout(input_path, tech.name)
56
+ layout_view = cell_view.view()
57
+
58
+ # Hide layers that shouldn't be shown in the current view.
59
+ for layer in layout_view.each_layer():
60
+ layer_ldt = f'{layer.source_layer}/{layer.source_datatype}'
61
+ layer_name = layer.source_name
62
+ if not layer_name:
63
+ layer_name = layer.name
64
+ print_layer = layer_name
65
+ if ' ' in layer_name:
66
+ layer_name = layer_name.split()[0]
67
+ if (layer_name in sc_hide_layers) or \
68
+ (layer_ldt in sc_hide_layers):
69
+ print(f"[INFO] Turning off layer: {print_layer} : {layer_ldt}")
70
+ layer.visible = False
71
+
72
+ # If 'screenshot' mode is set, save image and exit.
73
+ if screenshot:
74
+ xbins = int(schema.get('tool', 'klayout', 'task', task, 'var', 'xbins',
75
+ step=step, index=index)[0])
76
+ ybins = int(schema.get('tool', 'klayout', 'task', task, 'var', 'ybins',
77
+ step=step, index=index)[0])
78
+
79
+ if xbins == 1 and ybins == 1:
80
+ __screenshot(schema, layout_view, output_path)
81
+ else:
82
+ __screenshot_montage(schema, layout_view, xbins, ybins)
83
+
84
+
85
+ def __screenshot(schema, layout_view, output_path):
86
+ flow = schema.get('option', 'flow')
87
+ step = schema.get('arg', 'step')
88
+ index = schema.get('arg', 'index')
89
+ task = schema.get('flowgraph', flow, step, index, 'task')
90
+
91
+ # Save a screenshot. TODO: Get aspect ratio from sc_cfg?
92
+ horizontal_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
93
+ 'show_horizontal_resolution',
94
+ step=step, index=index)[0])
95
+ vertical_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
96
+ 'show_vertical_resolution',
97
+ step=step, index=index)[0])
98
+
99
+ print(f'[INFO] Saving screenshot to {output_path}')
100
+ layout_view.save_image(output_path, horizontal_resolution, vertical_resolution)
101
+
102
+
103
+ def __screenshot_montage(schema, view, xbins, ybins):
104
+ flow = schema.get('option', 'flow')
105
+ step = schema.get('arg', 'step')
106
+ index = schema.get('arg', 'index')
107
+ task = schema.get('flowgraph', flow, step, index, 'task')
108
+
109
+ app = pya.Application.instance()
110
+ options = (
111
+ "grid-show-ruler",
112
+ "grid-visible",
113
+ "text-visible"
114
+ )
115
+ for option in options:
116
+ app.set_config(option, "false")
117
+
118
+ app.set_config("background-color", "#000000") # Black
119
+
120
+ design = schema.get('option', 'entrypoint')
121
+ if not design:
122
+ design = schema.get('design')
123
+
124
+ horizontal_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
125
+ 'show_horizontal_resolution',
126
+ step=step, index=index)[0])
127
+ vertical_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
128
+ 'show_vertical_resolution',
129
+ step=step, index=index)[0])
130
+ margin = float(schema.get('tool', 'klayout', 'task', task, 'var',
131
+ 'margin',
132
+ step=step, index=index)[0])
133
+ linewidth = int(schema.get('tool', 'klayout', 'task', task, 'var',
134
+ 'linewidth',
135
+ step=step, index=index)[0])
136
+ oversampling = int(schema.get('tool', 'klayout', 'task', task, 'var',
137
+ 'oversampling',
138
+ step=step, index=index)[0])
139
+
140
+ view.zoom_fit()
141
+ cell = view.active_cellview().cell
142
+
143
+ view_box = cell.dbbox()
144
+ view_box.left -= margin
145
+ view_box.bottom -= margin
146
+ view_box.right += margin
147
+ view_box.top += margin
148
+
149
+ x_incr = int(view_box.width() / xbins)
150
+ y_incr = int(view_box.height() / ybins)
151
+
152
+ if (view_box.width() > view_box.height()):
153
+ y_px = vertical_resolution
154
+ x_px = int((float(x_incr) / y_incr) * y_px)
155
+ else:
156
+ x_px = horizontal_resolution
157
+ y_px = int((float(y_incr) / x_incr) * x_px)
158
+
159
+ for x in range(xbins):
160
+ for y in range(ybins):
161
+ yidx = ybins - y - 1
162
+ output_file = f"{design}_X{x}_Y{yidx}.png"
163
+
164
+ x_start = view_box.left + x_incr * x
165
+ y_start = view_box.bottom + y_incr * y
166
+
167
+ subbox = pya.DBox(
168
+ x_start,
169
+ y_start,
170
+ x_start + x_incr,
171
+ y_start + y_incr)
172
+
173
+ sub_img_spec = {
174
+ "width": x_px,
175
+ "height": y_px,
176
+ "linewidth": linewidth,
177
+ "oversampling": oversampling,
178
+ "resolution": 0,
179
+ "target_box": subbox,
180
+ "monochrome": False
181
+ }
182
+
183
+ img_path = os.path.join('outputs', output_file)
184
+ print(f'[INFO] Saving screenshot (({subbox.left}, {subbox.bottom}), '
185
+ f'({subbox.right}, {subbox.top})) to {img_path}')
186
+ view.save_image_with_options(
187
+ img_path,
188
+ sub_img_spec["width"],
189
+ sub_img_spec["height"],
190
+ sub_img_spec["linewidth"],
191
+ sub_img_spec["oversampling"],
192
+ sub_img_spec["resolution"],
193
+ sub_img_spec["target_box"],
194
+ sub_img_spec["monochrome"]
195
+ )
196
+
197
+
198
+ def main():
199
+ # SC_ROOT provided by CLI, and is only accessible when this is main module
200
+ sys.path.append(SC_ROOT) # noqa: F821
201
+
202
+ from tools.klayout.klayout_utils import (
203
+ technology,
204
+ get_schema
205
+ )
206
+
207
+ schema = get_schema(manifest='sc_manifest.json')
208
+
209
+ flow = schema.get('option', 'flow')
210
+ step = schema.get('arg', 'step')
211
+ index = schema.get('arg', 'index')
212
+ task = schema.get('flowgraph', flow, step, index, 'task')
213
+
214
+ design = schema.get('option', 'entrypoint')
215
+ if not design:
216
+ design = schema.get('design')
217
+
218
+ if 'show_filepath' in schema.getkeys('tool', 'klayout', 'task', task, 'var') and \
219
+ schema.get('tool', 'klayout', 'task', task, 'var', 'show_filepath',
220
+ step=step, index=index):
221
+ sc_filename = schema.get('tool', 'klayout', 'task', task, 'var', 'show_filepath',
222
+ step=step, index=index)[0]
223
+ else:
224
+ sc_fileext = schema.get('tool', 'klayout', 'task', task, 'var', 'show_filetype',
225
+ step=step, index=index)[0]
226
+ for ext in (f'{sc_fileext}.gz', sc_fileext):
227
+ sc_filename = f"inputs/{design}.{ext}"
228
+ if os.path.exists(sc_filename):
229
+ break
230
+
231
+ sc_exit = schema.get('tool', 'klayout', 'task', task, 'var', 'show_exit',
232
+ step=step, index=index) == ["true"]
233
+
234
+ show(schema, technology(design, schema), sc_filename, f'outputs/{design}.png',
235
+ screenshot=(task == 'screenshot'))
236
+
237
+ if sc_exit:
238
+ pya.Application.instance().exit(0)
239
+
240
+
241
+ if __name__ == '__main__':
242
+ main()
@@ -0,0 +1,176 @@
1
+ import pya
2
+ import importlib.util as importlib_util
3
+ import os
4
+ import shutil
5
+ import sys
6
+
7
+
8
+ def get_streams(schema):
9
+ sc_step = schema.get('arg', 'step')
10
+ sc_index = schema.get('arg', 'index')
11
+ sc_flow = schema.get('option', 'flow')
12
+ sc_task = schema.get('flowgraph', sc_flow, sc_step, sc_index, 'task')
13
+
14
+ streams = ('gds', 'oas')
15
+ if schema.valid('tool', 'klayout', 'task', sc_task, 'var', 'stream'):
16
+ sc_stream = schema.get('tool', 'klayout', 'task', sc_task, 'var', 'stream',
17
+ step=sc_step, index=sc_index)[0]
18
+ else:
19
+ sc_stream = streams[0]
20
+ return [sc_stream, *[s for s in streams if s != sc_stream]]
21
+
22
+
23
+ def technology(design, schema):
24
+ from tools._common.asic import get_libraries
25
+
26
+ sc_step = schema.get('arg', 'step')
27
+ sc_index = schema.get('arg', 'index')
28
+ sc_pdk = schema.get('option', 'pdk')
29
+
30
+ if schema.valid('option', 'stackup'):
31
+ sc_stackup = schema.get('option', 'stackup')
32
+ else:
33
+ sc_stackup = schema.get('pdk', sc_pdk, 'stackup')[0]
34
+ sc_mainlib = schema.get('asic', 'logiclib', step=sc_step, index=sc_index)[0]
35
+ sc_libtype = schema.get('library', sc_mainlib, 'asic', 'libarch', step=sc_step, index=sc_index)
36
+
37
+ sc_libs = []
38
+ sc_libs += get_libraries(schema, 'logic')
39
+ sc_libs += get_libraries(schema, 'macro')
40
+
41
+ local_files = {
42
+ 'lyt': f'inputs/{design}.lyt',
43
+ 'lyp': f'inputs/{design}.lyp'
44
+ }
45
+
46
+ tech = pya.Technology.create_technology('sc_tech')
47
+ # Load technology file
48
+ tech_file = None
49
+ if os.path.exists(local_files['lyt']):
50
+ tech_file = local_files['lyt']
51
+ elif schema.valid('pdk', sc_pdk, 'layermap', 'klayout', 'def', 'klayout', sc_stackup):
52
+ tech_file = schema.get('pdk', sc_pdk, 'layermap', 'klayout', 'def', 'klayout', sc_stackup)
53
+ if tech_file:
54
+ tech_file = tech_file[0]
55
+
56
+ if tech_file:
57
+ print(f"[INFO] Loading technology file: {tech_file}")
58
+ tech.load(tech_file)
59
+ else:
60
+ tech.name = f'{sc_pdk} for {sc_stackup}'
61
+ tech.description = f'{", ".join(sc_libs)}'
62
+
63
+ if schema.valid('pdk', sc_pdk, 'var', 'klayout', 'units', sc_stackup):
64
+ units = float(schema.get('pdk', sc_pdk, 'var', 'klayout', 'units', sc_stackup)[0])
65
+ tech.dbu = units
66
+ print(f"[INFO] Technology database units are: {tech.dbu}um")
67
+
68
+ lefs = []
69
+
70
+ foundry_lef = schema.get('pdk', sc_pdk, 'aprtech', 'klayout', sc_stackup, sc_libtype, 'lef')
71
+ if foundry_lef:
72
+ foundry_lef = foundry_lef[0]
73
+ lefs.append(foundry_lef)
74
+ else:
75
+ foundry_lef = None
76
+
77
+ for lib in sc_libs:
78
+ lefs.extend(schema.get('library', lib, 'output', sc_stackup, 'lef',
79
+ step=sc_step, index=sc_index))
80
+
81
+ layoutOptions = tech.load_layout_options
82
+
83
+ layoutOptions.lefdef_config.macro_resolution_mode = 1
84
+ layoutOptions.lefdef_config.via_cellname_prefix = "VIA_"
85
+ pathed_files = set()
86
+ for lef_file in layoutOptions.lefdef_config.lef_files:
87
+ if foundry_lef and not os.path.isabs(lef_file):
88
+ lef_file = os.path.join(os.path.dirname(foundry_lef), lef_file)
89
+ lef_file = os.path.abspath(lef_file)
90
+ if os.path.isfile(lef_file):
91
+ pathed_files.add(os.path.abspath(lef_file))
92
+
93
+ for lef in lefs:
94
+ pathed_files.add(os.path.abspath(lef))
95
+
96
+ layoutOptions.lefdef_config.lef_files = list(pathed_files)
97
+ layoutOptions.lefdef_config.read_lef_with_def = False
98
+ layoutOptions.lefdef_config.dbu = tech.dbu
99
+
100
+ layoutOptions.lefdef_config.produce_fills = True
101
+
102
+ for lef_file in layoutOptions.lefdef_config.lef_files:
103
+ print(f"[INFO] LEF file: {lef_file}")
104
+
105
+ # Set layer properties
106
+ layer_properties = tech.layer_properties_file
107
+ if layer_properties:
108
+ layer_properties = layer_properties[0]
109
+ if not os.path.isabs(layer_properties):
110
+ layer_properties = os.path.abspath(os.path.join(os.path.dirname(tech_file),
111
+ layer_properties))
112
+ if os.path.exists(local_files['lyp']):
113
+ layer_properties = os.path.abspath(local_files['lyp'])
114
+ elif schema.valid('pdk', sc_pdk, 'display', 'klayout', sc_stackup):
115
+ pdk_layer_props = schema.get('pdk', sc_pdk, 'display', 'klayout', sc_stackup)
116
+ if pdk_layer_props:
117
+ layer_properties = pdk_layer_props[0]
118
+
119
+ if layer_properties and os.path.exists(layer_properties):
120
+ tech.layer_properties_file = layer_properties
121
+ print(f"[INFO] Layer properties: {layer_properties}")
122
+
123
+ # Set layer map
124
+ map_file = layoutOptions.lefdef_config.map_file
125
+ if map_file:
126
+ map_file = map_file[0]
127
+ if not os.path.isabs(map_file):
128
+ map_file = os.path.abspath(os.path.join(os.path.dirname(tech_file),
129
+ map_file))
130
+ for s in get_streams(schema):
131
+ if schema.valid('pdk', sc_pdk, 'layermap', 'klayout', 'def', s, sc_stackup):
132
+ map_file = schema.get('pdk', sc_pdk, 'layermap', 'klayout', 'def', s, sc_stackup)
133
+ if map_file:
134
+ map_file = map_file[0]
135
+ break
136
+
137
+ if map_file and os.path.exists(map_file):
138
+ layoutOptions.lefdef_config.map_file = map_file
139
+ print(f"[INFO] Layer map: {map_file}")
140
+
141
+ tech.load_layout_options = layoutOptions
142
+
143
+ return tech
144
+
145
+
146
+ def save_technology(design, tech):
147
+ tech.default_base_path = '.'
148
+ tech.base_path = '.'
149
+
150
+ if tech.layer_properties_file:
151
+ layer_file = f'{design}.lyp'
152
+ shutil.copyfile(tech.layer_properties_file,
153
+ f'outputs/{layer_file}')
154
+ tech.layer_properties_file = layer_file
155
+
156
+ tech.save(f'outputs/{design}.lyt')
157
+
158
+
159
+ def get_write_options(filename, timestamps):
160
+ write_options = pya.SaveLayoutOptions()
161
+ write_options.gds2_write_timestamps = timestamps
162
+ write_options.set_format_from_filename(filename)
163
+
164
+ return write_options
165
+
166
+
167
+ def get_schema(manifest):
168
+ scroot = os.path.join(os.path.dirname(__file__), '..', '..')
169
+ module_name = 'schema'
170
+ schema_base = os.path.join(scroot, module_name, '__init__.py')
171
+ spec = importlib_util.spec_from_file_location(module_name, schema_base)
172
+ module = importlib_util.module_from_spec(spec)
173
+ sys.modules[module_name] = module
174
+ spec.loader.exec_module(module)
175
+ # Return schema
176
+ return module.Schema(manifest=manifest)
@@ -0,0 +1,194 @@
1
+ from siliconcompiler import SiliconCompilerError
2
+ from siliconcompiler.tools.klayout.klayout import setup as setup_tool
3
+ from siliconcompiler.tools._common import input_provides, get_tool_task
4
+
5
+
6
+ def setup(chip):
7
+ '''
8
+ Perform unit operations on stream files. Currently supports:
9
+
10
+ * rotating (rotate)
11
+ * renaming (rename)
12
+ * merging streams (merge)
13
+ * adding streams together (add)
14
+ * adding outline to top (outline)
15
+ * swapping cells (swap)
16
+ * adding new top cell (add_top)
17
+ * renaming cells (rename_cell)
18
+ * flatten
19
+ * deleting layers
20
+ * merging shapes
21
+ * writing (write)
22
+ * converting properties into text labels on design (convert_property)
23
+
24
+ To rotate:
25
+
26
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', 'rotate')
27
+
28
+ To rename:
29
+
30
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
31
+ 'rename:tool,klayout,task,operations,var,new_name')
32
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'new_name', \\
33
+ 'chip_top')
34
+
35
+ To merge streams:
36
+
37
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
38
+ 'merge:tool,klayout,task,operations,file,fill_stream')
39
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'file', 'fill_stream', \\
40
+ './fill.gds')
41
+
42
+ or to get it from the inputs to this task:
43
+
44
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
45
+ 'merge:fill.gds')
46
+
47
+ To add streams:
48
+
49
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
50
+ 'add:tool,klayout,task,operations,file,fill_stream')
51
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'file', 'fill_stream', \\
52
+ './fill.gds')
53
+
54
+ or to get it from the inputs to this task:
55
+
56
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
57
+ 'add:fill.gds')
58
+
59
+ To add outline:
60
+
61
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
62
+ 'outline:tool,klayout,task,operations,var,outline')
63
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'outline', \\
64
+ ['10', '1']) # layer / purpose pair
65
+
66
+ To swap layout cells:
67
+
68
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
69
+ 'swap:tool,klayout,task,operations,var,cell_swap')
70
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'cell_swap', \\
71
+ ['dummy_ANDX2=ANDX2', 'dummy_NANDX2=NANDX2'])
72
+
73
+ To rename cells:
74
+
75
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
76
+ 'rename_cell:tool,klayout,task,operations,var,rename_cell')
77
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'rename_cell', \\
78
+ ['dummy_ANDX2=ANDX2', 'dummy_NANDX2=NANDX2'])
79
+
80
+ To add new top cell:
81
+
82
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
83
+ 'add_top:tool,klayout,task,operations,var,new_name')
84
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'new_name', \\
85
+ 'chip_top')
86
+
87
+ To write out a new file:
88
+
89
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
90
+ 'write:combined.gds')
91
+
92
+ To convert stream properties to text labels:
93
+
94
+ >>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
95
+ 'convert_property:tool,klayout,task,operations,var,convert_c4_bumps')
96
+ >>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'convert_c4_bumps', \\
97
+ ['10', '2', \\ # layer / purpose pair for the source of the labels
98
+ '3' \\ # stream property number
99
+ '85', '5']) # (optional) destination layer / purpose pair, if not provided
100
+ # the source pair will be used instead.
101
+ '''
102
+
103
+ # Generic tool setup.
104
+ setup_tool(chip)
105
+
106
+ tool = 'klayout'
107
+ step = chip.get('arg', 'step')
108
+ index = chip.get('arg', 'index')
109
+ _, task = get_tool_task(chip, step, index)
110
+ clobber = False
111
+
112
+ script = 'klayout_operations.py'
113
+ option = ['-z', '-nc', '-rx', '-r']
114
+ chip.set('tool', tool, 'task', task, 'script', script, step=step, index=index, clobber=clobber)
115
+ chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index, clobber=clobber)
116
+
117
+ # Set stream extension
118
+ streams = ('gds', 'oas')
119
+ chip.set('tool', tool, 'task', task, 'var', 'stream', 'gds',
120
+ step=step, index=index, clobber=False)
121
+ chip.set('tool', tool, 'task', task, 'var', 'stream',
122
+ f'Extension to use for stream generation ({streams})',
123
+ field='help')
124
+ default_stream = chip.get('tool', tool, 'task', task, 'var', 'stream',
125
+ step=step, index=index)[0]
126
+ # Input/Output requirements for default flow
127
+ design = chip.top()
128
+ if f'{design}.{default_stream}' in input_provides(chip, step, index):
129
+ chip.add('tool', tool, 'task', task, 'input', f'{design}.{default_stream}',
130
+ step=step, index=index)
131
+ else:
132
+ chip.add('tool', tool, 'task', task, 'require', f'input,layout,{default_stream}')
133
+ chip.add('tool', tool, 'task', task, 'output', f'{design}.{default_stream}',
134
+ step=step, index=index)
135
+
136
+ # Export GDS with timestamps by default.
137
+ chip.set('tool', tool, 'task', task, 'var', 'timestamps', 'true',
138
+ step=step, index=index, clobber=False)
139
+ chip.set('tool', tool, 'task', task, 'var', 'timestamps',
140
+ 'Export GDSII with timestamps',
141
+ field='help')
142
+
143
+ klayout_ops = ('merge',
144
+ 'add',
145
+ 'rotate',
146
+ 'outline',
147
+ 'rename',
148
+ 'swap',
149
+ 'add_top',
150
+ 'write',
151
+ 'convert_property',
152
+ 'flatten',
153
+ 'merge_shapes',
154
+ 'delete_layers',
155
+ 'rename_cell')
156
+ ops = chip.get('tool', tool, 'task', task, 'var', 'operations', step=step, index=index)
157
+ for op in ops:
158
+ klayout_op = op.split(':', 1)
159
+ if len(klayout_op) == 1:
160
+ klayout_op = klayout_op[0]
161
+ args = ""
162
+ else:
163
+ klayout_op, args = klayout_op
164
+
165
+ if klayout_op not in klayout_ops:
166
+ raise SiliconCompilerError(
167
+ f'{klayout_op} is not a supported operation in klayout: {klayout_ops}',
168
+ chip=chip)
169
+
170
+ if klayout_op in ('add', 'merge'):
171
+ if ',' in args:
172
+ chip.add('tool', tool, 'task', task, 'require', args, step=step, index=index)
173
+ elif args:
174
+ chip.add('tool', tool, 'task', task, 'input', args, step=step, index=index)
175
+ else:
176
+ raise SiliconCompilerError(
177
+ f'{klayout_op} requires a filename to read or a keypath', chip=chip)
178
+ elif klayout_op in ('outline',
179
+ 'rename',
180
+ 'swap',
181
+ 'add_top',
182
+ 'convert_property',
183
+ 'merge_shapes',
184
+ 'delete_layers',
185
+ 'rename_cell'):
186
+ chip.add('tool', tool, 'task', task, 'require', args, step=step, index=index)
187
+ elif klayout_op in ('rotate', 'flatten'):
188
+ if args:
189
+ raise SiliconCompilerError('rotate does not take any arguments', chip=chip)
190
+ elif klayout_op in ('write'):
191
+ if not args:
192
+ raise SiliconCompilerError('write requires a filename to save to', chip=chip)
193
+ chip.add('tool', tool, 'task', task, 'output', args,
194
+ step=step, index=index)