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,423 @@
1
+ import contextlib
2
+ import os
3
+ import re
4
+ import psutil
5
+ import shutil
6
+ from pathlib import Path
7
+ from siliconcompiler._metadata import version as sc_version
8
+ from jinja2 import Environment, FileSystemLoader
9
+
10
+ import sys
11
+ if sys.version_info < (3, 10):
12
+ from importlib_metadata import entry_points
13
+ else:
14
+ from importlib.metadata import entry_points
15
+
16
+
17
+ PACKAGE_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18
+
19
+ _siliconcompiler_data_path = 'git+https://github.com/siliconcompiler/siliconcompiler'
20
+
21
+
22
+ def link_symlink_copy(srcfile, dstfile):
23
+ # first try hard linking, then symbolic linking,
24
+ # and finally just copy the file
25
+ for method in [os.link, os.symlink, shutil.copy2]:
26
+ try:
27
+ # create link
28
+ return method(srcfile, dstfile)
29
+ # success, no need to continue trying
30
+ except OSError:
31
+ pass
32
+
33
+
34
+ def link_copy(srcfile, dstfile):
35
+ # first try hard linking, then symbolic linking,
36
+ # and finally just copy the file
37
+ for method in [os.link, shutil.copy2]:
38
+ try:
39
+ # create link
40
+ return method(srcfile, dstfile)
41
+ # success, no need to continue trying
42
+ except OSError:
43
+ pass
44
+
45
+
46
+ def terminate_process(pid, timeout=3):
47
+ '''Terminates a process and all its (grand+)children.
48
+
49
+ Based on https://psutil.readthedocs.io/en/latest/#psutil.wait_procs and
50
+ https://psutil.readthedocs.io/en/latest/#kill-process-tree.
51
+ '''
52
+ assert pid != os.getpid(), "won't terminate myself"
53
+ parent = psutil.Process(pid)
54
+ children = parent.children(recursive=True)
55
+ children.append(parent)
56
+ for p in children:
57
+ try:
58
+ p.terminate()
59
+ except psutil.NoSuchProcess:
60
+ # Process may have terminated on its own in the meantime
61
+ pass
62
+
63
+ _, alive = psutil.wait_procs(children, timeout=timeout)
64
+ for p in alive:
65
+ # If processes are still alive after timeout seconds, send more
66
+ # aggressive signal.
67
+ p.kill()
68
+
69
+
70
+ def get_file_ext(filename):
71
+ '''Get base file extension for a given path, disregarding .gz.'''
72
+ if filename.lower().endswith('.gz'):
73
+ filename = os.path.splitext(filename)[0]
74
+ filetype = os.path.splitext(filename)[1].lower().lstrip('.')
75
+ return filetype
76
+
77
+
78
+ def get_default_iomap():
79
+ """
80
+ Default input file map for SC with filesets and extensions
81
+ """
82
+
83
+ # Record extensions:
84
+
85
+ # High level languages
86
+ hll_c = ('c', 'cc', 'cpp', 'c++', 'cp', 'cxx', 'hpp')
87
+ hll_bsv = ('bsv',)
88
+ hll_scala = ('scala',)
89
+ hll_python = ('py',)
90
+
91
+ config_chisel = ('sbt',)
92
+
93
+ # Register transfer languages
94
+ rtl_verilog = ('v', 'verilog')
95
+ rtl_systemverilog = ('sv',)
96
+ rtl_vhdl = ('vhd', 'vhdl')
97
+
98
+ # Timing libraries
99
+ timing_liberty = ('lib', 'ccs')
100
+
101
+ # Layout
102
+ layout_def = ('def',)
103
+ layout_lef = ('lef',)
104
+ layout_gds = ('gds', 'gds2', 'gdsii')
105
+ layout_oas = ('oas', 'oasis')
106
+ layout_gerber = ('gbr', 'gerber')
107
+ layout_odb = ('odb',)
108
+
109
+ # Netlist
110
+ netlist_cdl = ('cdl',)
111
+ netlist_sp = ('sp', 'spice')
112
+ netlist_verilog = ('vg',)
113
+
114
+ # Waveform
115
+ waveform_vcd = ('vcd',)
116
+
117
+ # Constraint
118
+ constraint_sdc = ('sdc', )
119
+ constraint_upf = ('upf', )
120
+
121
+ # FPGA constraints
122
+ fpga_xdc = ('xdc',)
123
+ constraint_pcf = ('pcf',)
124
+ fpga_vpr_place = ('place',)
125
+ fpga_vpr_route = ('route',)
126
+
127
+ # Build default map with fileset and type
128
+ default_iomap = {}
129
+ default_iomap.update({ext: ('hll', 'c') for ext in hll_c})
130
+ default_iomap.update({ext: ('hll', 'bsv') for ext in hll_bsv})
131
+ default_iomap.update({ext: ('hll', 'scala') for ext in hll_scala})
132
+ default_iomap.update({ext: ('hll', 'python') for ext in hll_python})
133
+ default_iomap.update({ext: ('config', 'chisel') for ext in config_chisel})
134
+
135
+ default_iomap.update({ext: ('rtl', 'verilog') for ext in rtl_verilog})
136
+ default_iomap.update({ext: ('rtl', 'systemverilog') for ext in rtl_systemverilog})
137
+ default_iomap.update({ext: ('rtl', 'vhdl') for ext in rtl_vhdl})
138
+
139
+ default_iomap.update({ext: ('timing', 'liberty') for ext in timing_liberty})
140
+
141
+ default_iomap.update({ext: ('layout', 'def') for ext in layout_def})
142
+ default_iomap.update({ext: ('layout', 'lef') for ext in layout_lef})
143
+ default_iomap.update({ext: ('layout', 'gds') for ext in layout_gds})
144
+ default_iomap.update({ext: ('layout', 'oas') for ext in layout_oas})
145
+ default_iomap.update({ext: ('layout', 'gerber') for ext in layout_gerber})
146
+ default_iomap.update({ext: ('layout', 'odb') for ext in layout_odb})
147
+
148
+ default_iomap.update({ext: ('netlist', 'cdl') for ext in netlist_cdl})
149
+ default_iomap.update({ext: ('netlist', 'sp') for ext in netlist_sp})
150
+ default_iomap.update({ext: ('netlist', 'verilog') for ext in netlist_verilog})
151
+
152
+ default_iomap.update({ext: ('waveform', 'vcd') for ext in waveform_vcd})
153
+
154
+ default_iomap.update({ext: ('constraint', 'sdc') for ext in constraint_sdc})
155
+ default_iomap.update({ext: ('constraint', 'upf') for ext in constraint_upf})
156
+ default_iomap.update({ext: ('constraint', 'pcf') for ext in constraint_pcf})
157
+
158
+ default_iomap.update({ext: ('fpga', 'xdc') for ext in fpga_xdc})
159
+ default_iomap.update({ext: ('fpga', 'vpr_place') for ext in fpga_vpr_place})
160
+ default_iomap.update({ext: ('fpga', 'vpr_route') for ext in fpga_vpr_route})
161
+
162
+ return default_iomap
163
+
164
+
165
+ def format_fileset_type_table(indent=12):
166
+ '''
167
+ Generate a table to use in the __doc__ of the input function which auto
168
+ updates based on the iomap
169
+ '''
170
+ table = "filetype | fileset | suffix (case insensitive)\n"
171
+ indent = " " * indent
172
+ table += f"{indent}--------------|------------|---------------------------------------------\n"
173
+
174
+ iobytype = {}
175
+ for ext, settype in get_default_iomap().items():
176
+ fileset, filetype = settype
177
+ iobytype.setdefault((fileset, filetype), []).append(ext)
178
+
179
+ for settype, exts in iobytype.items():
180
+ fileset, filetype = settype
181
+ ext = ",".join(exts)
182
+ table += f"{indent}{filetype:<14}| {fileset:<11}| {ext}\n"
183
+
184
+ return table
185
+
186
+
187
+ def default_credentials_file():
188
+ cfg_file = os.path.join(Path.home(), '.sc', 'credentials')
189
+
190
+ return cfg_file
191
+
192
+
193
+ def default_cache_dir():
194
+ cfg_file = os.path.join(Path.home(), '.sc', 'cache')
195
+
196
+ return cfg_file
197
+
198
+
199
+ def default_email_credentials_file():
200
+ cfg_file = os.path.join(Path.home(), '.sc', 'email.json')
201
+
202
+ return cfg_file
203
+
204
+
205
+ def register_sc_data_source(chip):
206
+ chip.register_source('siliconcompiler_data',
207
+ _siliconcompiler_data_path,
208
+ 'v'+sc_version)
209
+
210
+
211
+ @contextlib.contextmanager
212
+ def sc_open(path, *args, **kwargs):
213
+ kwargs['errors'] = 'ignore_with_warning'
214
+ fobj = open(path, *args, **kwargs)
215
+ try:
216
+ with contextlib.closing(fobj):
217
+ yield fobj
218
+ finally:
219
+ pass
220
+
221
+
222
+ def get_file_template(path, root=os.path.join(PACKAGE_ROOT, 'templates')):
223
+ if os.path.isabs(path):
224
+ root = os.path.dirname(path)
225
+ path = os.path.basename(path)
226
+
227
+ env = Environment(loader=FileSystemLoader(root))
228
+ return env.get_template(path)
229
+
230
+
231
+ #######################################
232
+ def safecompare(chip, value, op, goal):
233
+ # supported relational operations
234
+ # >, >=, <=, <. ==, !=
235
+ if op == ">":
236
+ return bool(value > goal)
237
+ elif op == ">=":
238
+ return bool(value >= goal)
239
+ elif op == "<":
240
+ return bool(value < goal)
241
+ elif op == "<=":
242
+ return bool(value <= goal)
243
+ elif op == "==":
244
+ return bool(value == goal)
245
+ elif op == "!=":
246
+ return bool(value != goal)
247
+ else:
248
+ chip.error(f"Illegal comparison operation {op}")
249
+
250
+
251
+ ###########################################################################
252
+ def grep(chip, args, line):
253
+ """
254
+ Emulates the Unix grep command on a string.
255
+
256
+ Emulates the behavior of the Unix grep command that is etched into
257
+ our muscle memory. Partially implemented, not all features supported.
258
+ The function returns None if no match is found.
259
+
260
+ Args:
261
+ arg (string): Command line arguments for grep command
262
+ line (string): Line to process
263
+
264
+ Returns:
265
+ Result of grep command (string).
266
+
267
+ """
268
+
269
+ # Quick return if input is None
270
+ if line is None:
271
+ return None
272
+
273
+ # Partial list of supported grep options
274
+ options = {
275
+ '-v': False, # Invert the sense of matching
276
+ '-i': False, # Ignore case distinctions in patterns and data
277
+ '-E': False, # Interpret PATTERNS as extended regular expressions.
278
+ '-e': False, # Safe interpretation of pattern starting with "-"
279
+ '-x': False, # Select only matches that exactly match the whole line.
280
+ '-o': False, # Print only the match parts of a matching line
281
+ '-w': False} # Select only lines containing matches that form whole words.
282
+
283
+ # Split into repeating switches and everything else
284
+ match = re.match(r'\s*((?:\-\w\s)*)(.*)', args)
285
+
286
+ pattern = match.group(2)
287
+
288
+ # Split space separated switch string into list
289
+ switches = match.group(1).strip().split(' ')
290
+
291
+ # Find special -e switch update the pattern
292
+ for i in range(len(switches)):
293
+ if switches[i] == "-e":
294
+ if i != (len(switches)):
295
+ pattern = ' '.join(switches[i + 1:]) + " " + pattern
296
+ switches = switches[0:i + 1]
297
+ break
298
+ options["-e"] = True
299
+ elif switches[i] in options.keys():
300
+ options[switches[i]] = True
301
+ elif switches[i] != '':
302
+ chip.logger.error(switches[i])
303
+
304
+ # REGEX
305
+ # TODO: add all the other optinos
306
+ match = re.search(rf"({pattern})", line)
307
+ if bool(match) == bool(options["-v"]):
308
+ return None
309
+ else:
310
+ return line
311
+
312
+
313
+ #######################################
314
+ def _resolve_env_vars(chip, filepath):
315
+ if not filepath:
316
+ return None
317
+
318
+ env_save = os.environ.copy()
319
+ for env in chip.getkeys('option', 'env'):
320
+ os.environ[env] = chip.get('option', 'env', env)
321
+ resolved_path = os.path.expandvars(filepath)
322
+ os.environ.clear()
323
+ os.environ.update(env_save)
324
+
325
+ # variables that don't exist in environment get ignored by `expandvars`,
326
+ # but we can do our own error checking to ensure this doesn't result in
327
+ # silent bugs
328
+ envvars = re.findall(r'\$(\w+)', resolved_path)
329
+ for var in envvars:
330
+ chip.logger.warning(f'Variable {var} in {filepath} not defined in environment')
331
+
332
+ return resolved_path
333
+
334
+
335
+ ###########################################################################
336
+ def find_sc_file(chip, filename, missing_ok=False, search_paths=None):
337
+ """
338
+ Returns the absolute path for the filename provided.
339
+
340
+ Searches the for the filename provided and returns the absolute path.
341
+ If no valid absolute path is found during the search, None is returned.
342
+
343
+ Shell variables ('$' followed by strings consisting of numbers,
344
+ underscores, and digits) are replaced with the variable value.
345
+
346
+ Args:
347
+ filename (str): Relative or absolute filename.
348
+ missing_ok (bool): If False, error out if no valid absolute path
349
+ found, rather than returning None.
350
+ search_paths (list): List of directories to search under instead of
351
+ the defaults.
352
+
353
+ Returns:
354
+ Returns absolute path of 'filename' if found, otherwise returns
355
+ None.
356
+
357
+ Examples:
358
+ >>> chip._find_sc_file('flows/asicflow.py')
359
+ Returns the absolute path based on the sc installation directory.
360
+
361
+ """
362
+
363
+ if not filename:
364
+ return None
365
+
366
+ # Replacing environment variables
367
+ filename = _resolve_env_vars(chip, filename)
368
+
369
+ # If we have an absolute path, pass-through here
370
+ if os.path.isabs(filename) and os.path.exists(filename):
371
+ return filename
372
+
373
+ # Otherwise, search relative to search_paths
374
+ if search_paths is None:
375
+ search_paths = [chip.cwd]
376
+
377
+ searchdirs = ', '.join([str(p) for p in search_paths])
378
+ chip.logger.debug(f"Searching for file {filename} in {searchdirs}")
379
+
380
+ result = None
381
+ for searchdir in search_paths:
382
+ if not os.path.isabs(searchdir):
383
+ searchdir = os.path.join(chip.cwd, searchdir)
384
+
385
+ abspath = os.path.abspath(os.path.join(searchdir, filename))
386
+ if os.path.exists(abspath):
387
+ result = abspath
388
+ break
389
+
390
+ if result is None and not missing_ok:
391
+ chip.error(f"File {filename} was not found")
392
+
393
+ return result
394
+
395
+
396
+ def get_plugins(system):
397
+ '''
398
+ Search for python modules with a specific function
399
+ '''
400
+
401
+ plugins = []
402
+ discovered_plugins = entry_points(group=f'siliconcompiler.{system}')
403
+ for plugin in discovered_plugins:
404
+ plugins.append(plugin.load())
405
+
406
+ return plugins
407
+
408
+
409
+ def truncate_text(text, width):
410
+ if len(text) <= width:
411
+ return text
412
+
413
+ keep_end = 0
414
+ while text[-1 - keep_end].isnumeric():
415
+ if keep_end >= 2:
416
+ break
417
+ keep_end += 1
418
+
419
+ while len(text) > width:
420
+ break_at = len(text) - keep_end - 3
421
+ text = text[:break_at-1] + '...' + text[break_at+3:]
422
+
423
+ return text
@@ -0,0 +1,158 @@
1
+ import math
2
+
3
+
4
+ ###########################################################################
5
+ def calc_area(chip, step=None, index=None):
6
+ '''Calculates the area of a rectilinear diearea.
7
+
8
+ Uses the shoelace formulate to calculate the design area using
9
+ the (x,y) point tuples from the 'diearea' parameter. If only diearea
10
+ parameter only contains two points, then the first and second point
11
+ must be the lower left and upper right points of the rectangle.
12
+ (Ref: https://en.wikipedia.org/wiki/Shoelace_formula)
13
+
14
+ Args:
15
+ step (str): name of the step to calculate the area from
16
+ index (str): name of the step to calculate the area from
17
+
18
+ Returns:
19
+ Design area (float).
20
+
21
+ Examples:
22
+ >>> area = chip.calc_area()
23
+
24
+ '''
25
+
26
+ if not step:
27
+ step = chip.get('arg', 'step')
28
+
29
+ if not index:
30
+ index = chip.get('arg', 'index')
31
+
32
+ vertices = chip.get('constraint', 'outline', step=step, index=index)
33
+
34
+ if len(vertices) == 2:
35
+ width = vertices[1][0] - vertices[0][0]
36
+ height = vertices[1][1] - vertices[0][1]
37
+ area = width * height
38
+ else:
39
+ area = 0.0
40
+ for i in range(len(vertices)):
41
+ j = (i + 1) % len(vertices)
42
+ area += vertices[i][0] * vertices[j][1]
43
+ area -= vertices[j][0] * vertices[i][1]
44
+ area = abs(area) / 2
45
+
46
+ return area
47
+
48
+
49
+ ###########################################################################
50
+ def calc_yield(chip, step=None, index=None, model='poisson'):
51
+ '''Calculates raw die yield.
52
+
53
+ Calculates the raw yield of the design as a function of design area
54
+ and d0 defect density. Calculation can be done based on the poisson
55
+ model (default) or the murphy model. The die area and the d0
56
+ parameters are taken from the chip dictionary.
57
+
58
+ * Poisson model: dy = exp(-area * d0/100).
59
+ * Murphy model: dy = ((1-exp(-area * d0/100))/(area * d0/100))^2.
60
+
61
+ Args:
62
+ step (str): name of the step use for calculation
63
+ index (str): name of the step use for calculation
64
+ model (string): Model to use for calculation (poisson or murphy)
65
+
66
+ Returns:
67
+ Design yield percentage (float).
68
+
69
+ Examples:
70
+ >>> yield = chip.calc_yield()
71
+ Yield variable gets yield value based on the chip manifest.
72
+ '''
73
+
74
+ pdk = chip.get('option', 'pdk')
75
+ d0 = chip.get('pdk', pdk, 'd0')
76
+ if d0 is None:
77
+ chip.error(f"['pdk', {pdk}, 'd0'] has not been set")
78
+ diearea = calc_area(chip, step=step, index=index)
79
+
80
+ # diearea is um^2, but d0 looking for cm^2
81
+ diearea = diearea / 10000.0**2
82
+
83
+ if model == 'poisson':
84
+ dy = math.exp(-diearea * d0 / 100)
85
+ elif model == 'murphy':
86
+ dy = ((1 - math.exp(-diearea * d0 / 100)) / (diearea * d0 / 100))**2
87
+ else:
88
+ chip.error(f'Unknown yield model: {model}')
89
+
90
+ return dy
91
+
92
+
93
+ ##########################################################################
94
+ def calc_dpw(chip, step=None, index=None):
95
+ '''Calculates dies per wafer.
96
+
97
+ Calculates the gross dies per wafer based on the design area, wafersize,
98
+ wafer edge margin, and scribe lines. The calculation is done by starting
99
+ at the center of the wafer and placing as many complete design
100
+ footprints as possible within a legal placement area.
101
+
102
+ Args:
103
+ step (str): name of the step use for calculation
104
+ index (str): name of the step use for calculation
105
+
106
+ Returns:
107
+ Number of gross dies per wafer (int).
108
+
109
+ Examples:
110
+ >>> dpw = chip.calc_dpw()
111
+ Variable dpw gets gross dies per wafer value based on the chip manifest.
112
+ '''
113
+
114
+ # PDK information
115
+ pdk = chip.get('option', 'pdk')
116
+ wafersize = chip.get('pdk', pdk, 'wafersize')
117
+ edgemargin = chip.get('pdk', pdk, 'edgemargin')
118
+ hscribe, vscribe = chip.get('pdk', pdk, 'scribe')
119
+
120
+ # Design parameters
121
+ diesize = chip.get('constraint', 'outline', step=step, index=index)
122
+
123
+ # Convert to mm
124
+ diewidth = (diesize[1][0] - diesize[0][0]) / 1000.0
125
+ dieheight = (diesize[1][1] - diesize[0][1]) / 1000.0
126
+
127
+ # Derived parameters
128
+ radius = wafersize / 2 - edgemargin
129
+ stepwidth = diewidth + hscribe
130
+ stepheight = dieheight + vscribe
131
+
132
+ # Raster dies out from center until you touch edge margin
133
+ # Work quadrant by quadrant
134
+ dies = 0
135
+ for quad in ('q1', 'q2', 'q3', 'q4'):
136
+ x = 0
137
+ y = 0
138
+ if quad == "q1":
139
+ xincr = stepwidth
140
+ yincr = stepheight
141
+ elif quad == "q2":
142
+ xincr = -stepwidth
143
+ yincr = stepheight
144
+ elif quad == "q3":
145
+ xincr = -stepwidth
146
+ yincr = -stepheight
147
+ elif quad == "q4":
148
+ xincr = stepwidth
149
+ yincr = -stepheight
150
+ # loop through all y values from center
151
+ while math.hypot(0, y) < radius:
152
+ y = y + yincr
153
+ x = xincr
154
+ while math.hypot(x, y) < radius:
155
+ x = x + xincr
156
+ dies = dies + 1
157
+
158
+ return dies
@@ -0,0 +1,25 @@
1
+ from siliconcompiler.tools.klayout import show as klayout_show
2
+ from siliconcompiler.tools.klayout import screenshot as klayout_screenshot
3
+ from siliconcompiler.tools.openroad import show as openroad_show
4
+ from siliconcompiler.tools.openroad import screenshot as openroad_screenshot
5
+ from siliconcompiler.tools.vpr import show as vpr_show
6
+ from siliconcompiler.tools.vpr import screenshot as vpr_screenshot
7
+
8
+
9
+ def setup(chip):
10
+ chip.register_showtool('gds', klayout_show)
11
+ chip.register_showtool('gds', klayout_screenshot)
12
+ chip.register_showtool('oas', klayout_show)
13
+ chip.register_showtool('oas', klayout_screenshot)
14
+ chip.register_showtool('lef', klayout_show)
15
+ chip.register_showtool('lef', klayout_screenshot)
16
+
17
+ chip.register_showtool('odb', openroad_show)
18
+ chip.register_showtool('odb', openroad_screenshot)
19
+ chip.register_showtool('def', openroad_show)
20
+ chip.register_showtool('def', openroad_screenshot)
21
+
22
+ chip.register_showtool('route', vpr_show)
23
+ chip.register_showtool('route', vpr_screenshot)
24
+ chip.register_showtool('place', vpr_show)
25
+ chip.register_showtool('place', vpr_screenshot)