siliconcompiler 0.32.3__py3-none-any.whl → 0.33.1__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 (280) hide show
  1. siliconcompiler/__init__.py +19 -2
  2. siliconcompiler/_common.py +5 -0
  3. siliconcompiler/_metadata.py +1 -1
  4. siliconcompiler/apps/sc.py +2 -2
  5. siliconcompiler/apps/sc_install.py +10 -3
  6. siliconcompiler/apps/sc_issue.py +1 -1
  7. siliconcompiler/apps/sc_remote.py +10 -5
  8. siliconcompiler/apps/sc_show.py +2 -2
  9. siliconcompiler/apps/utils/replay.py +5 -3
  10. siliconcompiler/asic.py +120 -0
  11. siliconcompiler/checklist.py +150 -0
  12. siliconcompiler/core.py +299 -299
  13. siliconcompiler/flowgraph.py +803 -515
  14. siliconcompiler/fpga.py +84 -0
  15. siliconcompiler/metric.py +479 -0
  16. siliconcompiler/optimizer/vizier.py +2 -3
  17. siliconcompiler/package/__init__.py +29 -6
  18. siliconcompiler/pdk.py +415 -0
  19. siliconcompiler/record.py +453 -0
  20. siliconcompiler/remote/client.py +15 -5
  21. siliconcompiler/remote/schema.py +116 -112
  22. siliconcompiler/remote/server.py +9 -6
  23. siliconcompiler/report/dashboard/cli/__init__.py +14 -721
  24. siliconcompiler/report/dashboard/cli/board.py +899 -0
  25. siliconcompiler/report/dashboard/web/__init__.py +10 -10
  26. siliconcompiler/report/dashboard/web/components/__init__.py +5 -4
  27. siliconcompiler/report/dashboard/web/components/flowgraph.py +3 -3
  28. siliconcompiler/report/dashboard/web/components/graph.py +6 -3
  29. siliconcompiler/report/dashboard/web/state.py +1 -1
  30. siliconcompiler/report/dashboard/web/utils/__init__.py +4 -3
  31. siliconcompiler/report/html_report.py +2 -3
  32. siliconcompiler/report/report.py +22 -11
  33. siliconcompiler/report/summary_image.py +1 -1
  34. siliconcompiler/report/summary_table.py +3 -3
  35. siliconcompiler/report/utils.py +21 -14
  36. siliconcompiler/scheduler/__init__.py +234 -1206
  37. siliconcompiler/scheduler/run_node.py +2 -1
  38. siliconcompiler/scheduler/send_messages.py +11 -5
  39. siliconcompiler/scheduler/slurm.py +11 -44
  40. siliconcompiler/scheduler/taskscheduler.py +320 -0
  41. siliconcompiler/schema/__init__.py +19 -2
  42. siliconcompiler/schema/baseschema.py +493 -0
  43. siliconcompiler/schema/cmdlineschema.py +250 -0
  44. siliconcompiler/{sphinx_ext → schema/docs}/__init__.py +3 -1
  45. siliconcompiler/{sphinx_ext → schema/docs}/dynamicgen.py +63 -81
  46. siliconcompiler/{sphinx_ext → schema/docs}/schemagen.py +73 -85
  47. siliconcompiler/{sphinx_ext → schema/docs}/utils.py +12 -13
  48. siliconcompiler/schema/editableschema.py +136 -0
  49. siliconcompiler/schema/journalingschema.py +238 -0
  50. siliconcompiler/schema/namedschema.py +41 -0
  51. siliconcompiler/schema/packageschema.py +101 -0
  52. siliconcompiler/schema/parameter.py +791 -0
  53. siliconcompiler/schema/parametertype.py +323 -0
  54. siliconcompiler/schema/parametervalue.py +736 -0
  55. siliconcompiler/schema/safeschema.py +37 -0
  56. siliconcompiler/schema/schema_cfg.py +109 -1789
  57. siliconcompiler/schema/utils.py +5 -68
  58. siliconcompiler/schema_obj.py +119 -0
  59. siliconcompiler/tool.py +1416 -0
  60. siliconcompiler/tools/_common/__init__.py +6 -10
  61. siliconcompiler/tools/_common/asic.py +5 -5
  62. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +1 -1
  63. siliconcompiler/tools/bluespec/convert.py +9 -8
  64. siliconcompiler/tools/builtin/_common.py +9 -2
  65. siliconcompiler/tools/builtin/concatenate.py +7 -3
  66. siliconcompiler/tools/builtin/minimum.py +7 -2
  67. siliconcompiler/tools/builtin/mux.py +8 -2
  68. siliconcompiler/tools/builtin/nop.py +7 -2
  69. siliconcompiler/tools/builtin/verify.py +11 -5
  70. siliconcompiler/tools/chisel/convert.py +10 -10
  71. siliconcompiler/tools/genfasm/bitstream.py +3 -3
  72. siliconcompiler/tools/ghdl/convert.py +1 -1
  73. siliconcompiler/tools/icarus/compile.py +4 -4
  74. siliconcompiler/tools/icepack/bitstream.py +6 -1
  75. siliconcompiler/tools/klayout/convert_drc_db.py +5 -0
  76. siliconcompiler/tools/klayout/drc.py +2 -2
  77. siliconcompiler/tools/klayout/klayout_export.py +0 -1
  78. siliconcompiler/tools/klayout/klayout_show.py +6 -6
  79. siliconcompiler/tools/klayout/klayout_utils.py +15 -22
  80. siliconcompiler/tools/netgen/count_lvs.py +2 -2
  81. siliconcompiler/tools/netgen/lvs.py +1 -1
  82. siliconcompiler/tools/nextpnr/apr.py +6 -1
  83. siliconcompiler/tools/nextpnr/nextpnr.py +4 -4
  84. siliconcompiler/tools/openroad/_apr.py +15 -2
  85. siliconcompiler/tools/openroad/rdlroute.py +3 -3
  86. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +1 -1
  87. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +5 -5
  88. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +2 -2
  89. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -2
  90. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +2 -2
  91. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -2
  92. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +2 -2
  93. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +2 -2
  94. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +2 -2
  95. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +2 -2
  96. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -2
  97. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +3 -9
  98. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +3 -3
  99. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +2 -2
  100. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +2 -2
  101. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +2 -2
  102. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +2 -2
  103. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +2 -2
  104. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +2 -2
  105. siliconcompiler/tools/openroad/scripts/common/procs.tcl +75 -1
  106. siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -7
  107. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +2 -2
  108. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -3
  109. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +1 -1
  110. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -3
  111. siliconcompiler/tools/openroad/scripts/sc_show.tcl +6 -6
  112. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +10 -0
  113. siliconcompiler/tools/opensta/timing.py +11 -0
  114. siliconcompiler/tools/slang/__init__.py +13 -13
  115. siliconcompiler/tools/slang/elaborate.py +6 -6
  116. siliconcompiler/tools/slang/lint.py +1 -3
  117. siliconcompiler/tools/surelog/parse.py +4 -4
  118. siliconcompiler/tools/sv2v/convert.py +20 -3
  119. siliconcompiler/tools/verilator/compile.py +2 -2
  120. siliconcompiler/tools/verilator/verilator.py +3 -3
  121. siliconcompiler/tools/vpr/_xml_constraint.py +8 -8
  122. siliconcompiler/tools/vpr/place.py +1 -1
  123. siliconcompiler/tools/vpr/route.py +4 -4
  124. siliconcompiler/tools/vpr/screenshot.py +1 -1
  125. siliconcompiler/tools/vpr/show.py +5 -5
  126. siliconcompiler/tools/vpr/vpr.py +24 -24
  127. siliconcompiler/tools/xdm/convert.py +2 -2
  128. siliconcompiler/tools/xyce/simulate.py +1 -1
  129. siliconcompiler/tools/yosys/prepareLib.py +2 -2
  130. siliconcompiler/tools/yosys/sc_synth_asic.tcl +111 -63
  131. siliconcompiler/tools/yosys/screenshot.py +1 -1
  132. siliconcompiler/tools/yosys/syn_asic.py +7 -7
  133. siliconcompiler/toolscripts/_tools.json +12 -10
  134. siliconcompiler/toolscripts/rhel8/install-chisel.sh +9 -2
  135. siliconcompiler/toolscripts/rhel8/install-icarus.sh +10 -3
  136. siliconcompiler/toolscripts/rhel8/install-klayout.sh +8 -1
  137. siliconcompiler/toolscripts/rhel8/install-magic.sh +9 -2
  138. siliconcompiler/toolscripts/rhel8/install-montage.sh +1 -1
  139. siliconcompiler/toolscripts/rhel8/install-netgen.sh +9 -2
  140. siliconcompiler/toolscripts/rhel8/install-slang.sh +11 -4
  141. siliconcompiler/toolscripts/rhel8/install-surelog.sh +9 -2
  142. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +11 -4
  143. siliconcompiler/toolscripts/rhel8/install-verible.sh +11 -3
  144. siliconcompiler/toolscripts/rhel8/install-verilator.sh +10 -3
  145. siliconcompiler/toolscripts/rhel8/install-xyce.sh +15 -10
  146. siliconcompiler/toolscripts/rhel9/install-chisel.sh +9 -2
  147. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +9 -2
  148. siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +10 -3
  149. siliconcompiler/toolscripts/rhel9/install-icarus.sh +10 -3
  150. siliconcompiler/toolscripts/rhel9/install-klayout.sh +8 -1
  151. siliconcompiler/toolscripts/rhel9/install-magic.sh +9 -2
  152. siliconcompiler/toolscripts/rhel9/install-montage.sh +1 -1
  153. siliconcompiler/toolscripts/rhel9/install-netgen.sh +9 -2
  154. siliconcompiler/toolscripts/rhel9/install-openroad.sh +16 -3
  155. siliconcompiler/toolscripts/rhel9/install-opensta.sh +17 -5
  156. siliconcompiler/toolscripts/rhel9/install-slang.sh +11 -4
  157. siliconcompiler/toolscripts/rhel9/install-surelog.sh +9 -2
  158. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +11 -4
  159. siliconcompiler/toolscripts/rhel9/install-verible.sh +11 -3
  160. siliconcompiler/toolscripts/rhel9/install-verilator.sh +10 -3
  161. siliconcompiler/toolscripts/rhel9/install-vpr.sh +9 -2
  162. siliconcompiler/toolscripts/rhel9/install-xdm.sh +10 -2
  163. siliconcompiler/toolscripts/rhel9/install-xyce.sh +15 -10
  164. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +9 -2
  165. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +10 -3
  166. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +10 -2
  167. siliconcompiler/toolscripts/rhel9/install-yosys.sh +9 -2
  168. siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +10 -2
  169. siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +10 -3
  170. siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +9 -2
  171. siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +9 -2
  172. siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +9 -2
  173. siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +9 -2
  174. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +9 -2
  175. siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +8 -1
  176. siliconcompiler/toolscripts/ubuntu20/install-magic.sh +9 -2
  177. siliconcompiler/toolscripts/ubuntu20/install-montage.sh +1 -1
  178. siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +9 -2
  179. siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +9 -2
  180. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +16 -3
  181. siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +16 -5
  182. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +11 -4
  183. siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +9 -2
  184. siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +10 -2
  185. siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +11 -4
  186. siliconcompiler/toolscripts/ubuntu20/install-verible.sh +11 -3
  187. siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +9 -2
  188. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +10 -2
  189. siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +13 -8
  190. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +9 -2
  191. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +9 -2
  192. siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +10 -2
  193. siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +10 -3
  194. siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +9 -2
  195. siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +9 -2
  196. siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +9 -2
  197. siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +9 -2
  198. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +9 -2
  199. siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +8 -1
  200. siliconcompiler/toolscripts/ubuntu22/install-magic.sh +9 -2
  201. siliconcompiler/toolscripts/ubuntu22/install-montage.sh +1 -1
  202. siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +9 -2
  203. siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +9 -2
  204. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +16 -3
  205. siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +17 -5
  206. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +11 -4
  207. siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +9 -2
  208. siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +10 -2
  209. siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +11 -4
  210. siliconcompiler/toolscripts/ubuntu22/install-verible.sh +11 -3
  211. siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +9 -2
  212. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +9 -4
  213. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +10 -2
  214. siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +13 -8
  215. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +9 -2
  216. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +10 -3
  217. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +10 -2
  218. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +9 -2
  219. siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +12 -4
  220. siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +10 -3
  221. siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +9 -2
  222. siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +9 -2
  223. siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +9 -2
  224. siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +9 -2
  225. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +9 -2
  226. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +8 -1
  227. siliconcompiler/toolscripts/ubuntu24/install-magic.sh +9 -2
  228. siliconcompiler/toolscripts/ubuntu24/install-montage.sh +1 -1
  229. siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +9 -2
  230. siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +9 -2
  231. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +16 -3
  232. siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +17 -5
  233. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +11 -4
  234. siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +9 -2
  235. siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +10 -2
  236. siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +11 -4
  237. siliconcompiler/toolscripts/ubuntu24/install-verible.sh +11 -3
  238. siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +9 -2
  239. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +9 -4
  240. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +10 -2
  241. siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +13 -8
  242. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +9 -2
  243. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +10 -3
  244. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +10 -2
  245. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +9 -2
  246. siliconcompiler/utils/__init__.py +19 -112
  247. siliconcompiler/utils/flowgraph.py +244 -0
  248. siliconcompiler/{issue.py → utils/issue.py} +18 -25
  249. siliconcompiler/utils/logging.py +3 -4
  250. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/METADATA +9 -8
  251. siliconcompiler-0.33.1.dist-info/RECORD +488 -0
  252. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/WHEEL +1 -1
  253. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/entry_points.txt +8 -8
  254. siliconcompiler/schema/schema_obj.py +0 -1936
  255. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +0 -29
  256. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +0 -61
  257. siliconcompiler-0.32.3.dist-info/RECORD +0 -470
  258. /siliconcompiler/{templates → data/templates}/__init__.py +0 -0
  259. /siliconcompiler/{templates → data/templates}/email/__init__.py +0 -0
  260. /siliconcompiler/{templates → data/templates}/email/general.j2 +0 -0
  261. /siliconcompiler/{templates → data/templates}/email/summary.j2 +0 -0
  262. /siliconcompiler/{templates → data/templates}/issue/README.txt +0 -0
  263. /siliconcompiler/{templates → data/templates}/issue/__init__.py +0 -0
  264. /siliconcompiler/{templates → data/templates}/issue/run.sh +0 -0
  265. /siliconcompiler/{templates → data/templates}/replay/replay.py.j2 +0 -0
  266. /siliconcompiler/{templates → data/templates}/replay/replay.sh.j2 +0 -0
  267. /siliconcompiler/{templates → data/templates}/replay/requirements.txt +0 -0
  268. /siliconcompiler/{templates → data/templates}/replay/setup.sh +0 -0
  269. /siliconcompiler/{templates → data/templates}/report/__init__.py +0 -0
  270. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.css +0 -0
  271. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.js +0 -0
  272. /siliconcompiler/{templates → data/templates}/report/bootstrap_LICENSE.md +0 -0
  273. /siliconcompiler/{templates → data/templates}/report/sc_report.j2 +0 -0
  274. /siliconcompiler/{templates → data/templates}/slurm/__init__.py +0 -0
  275. /siliconcompiler/{templates → data/templates}/slurm/run.sh +0 -0
  276. /siliconcompiler/{templates → data/templates}/tcl/__init__.py +0 -0
  277. /siliconcompiler/{templates → data/templates}/tcl/manifest.tcl.j2 +0 -0
  278. /siliconcompiler/{units.py → utils/units.py} +0 -0
  279. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/licenses/LICENSE +0 -0
  280. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,493 @@
1
+ # Copyright 2025 Silicon Compiler Authors. All Rights Reserved.
2
+
3
+ # NOTE: this file cannot rely on any third-party dependencies, including other
4
+ # SC dependencies outside of its directory, since it may be used by tool drivers
5
+ # that have isolated Python environments.
6
+
7
+ import copy
8
+
9
+ try:
10
+ import gzip
11
+ _has_gzip = True
12
+ except ModuleNotFoundError:
13
+ _has_gzip = False
14
+
15
+ try:
16
+ import orjson as json
17
+ _has_orjson = True
18
+ except ModuleNotFoundError:
19
+ import json
20
+ _has_orjson = False
21
+
22
+ import os.path
23
+
24
+ from .parameter import Parameter
25
+
26
+
27
+ class BaseSchema:
28
+ '''
29
+ This class maintains the access and file IO operations for the schema.
30
+ It can be modified using :class:`EditableSchema`.
31
+ '''
32
+
33
+ def __init__(self):
34
+ # Data storage for the schema
35
+ self.__manifest = {}
36
+ self.__default = None
37
+
38
+ def _from_dict(self, manifest, keypath, version=None):
39
+ '''
40
+ Decodes a dictionary into a schema object
41
+
42
+ Args:
43
+ manifest (dict): Manifest to decide.
44
+ keypath (list of str): Path to the current keypath.
45
+ version (packaging.Version): Version of the dictionary schema
46
+ '''
47
+
48
+ handled = set()
49
+ missing = set()
50
+
51
+ if self.__default:
52
+ data = manifest.get("default", None)
53
+ if data:
54
+ del manifest["default"]
55
+ self.__default._from_dict(data, keypath + ["default"], version=version)
56
+ handled.add("default")
57
+
58
+ for key, data in manifest.items():
59
+ obj = self.__manifest.get(key, None)
60
+ if not obj and self.__default:
61
+ obj = self.__default.copy()
62
+ self.__manifest[key] = obj
63
+ if obj:
64
+ obj._from_dict(data, keypath + [key], version=version)
65
+ handled.add(key)
66
+ else:
67
+ missing.add(key)
68
+
69
+ return missing, set(self.__manifest.keys()).difference(handled)
70
+
71
+ # Manifest methods
72
+ @classmethod
73
+ def from_manifest(cls, filepath=None, cfg=None):
74
+ '''
75
+ Create a new schema based on the provided source files.
76
+
77
+ The two arguments to this class are mutually exclusive.
78
+
79
+ Args:
80
+ filepath (path): Initial manifest.
81
+ cfg (dict): Initial configuration dictionary.
82
+ '''
83
+
84
+ schema = cls()
85
+ if not filepath and cfg is None:
86
+ raise RuntimeError("filepath or dictionary is required")
87
+ if filepath:
88
+ schema.read_manifest(filepath)
89
+ if cfg:
90
+ schema._from_dict(cfg, [])
91
+ return schema
92
+
93
+ @staticmethod
94
+ def __open_file(filepath, is_read=True):
95
+ _, ext = os.path.splitext(filepath)
96
+ if ext.lower() == ".gz":
97
+ if not _has_gzip:
98
+ raise RuntimeError("gzip is not available")
99
+ return gzip.open(filepath, mode="rt" if is_read else "wt", encoding="utf-8")
100
+ return open(filepath, mode="r" if is_read else "w", encoding="utf-8")
101
+
102
+ def read_manifest(self, filepath):
103
+ """
104
+ Reads a manifest from disk and replaces the current data with the data in the file.
105
+
106
+ Args:
107
+ filename (path): Path to a manifest file to be loaded.
108
+
109
+ Examples:
110
+ >>> schema.read_manifest('mychip.json')
111
+ Loads the file mychip.json into the current Schema object.
112
+ """
113
+
114
+ fin = BaseSchema.__open_file(filepath)
115
+ manifest = json.loads(fin.read())
116
+ fin.close()
117
+
118
+ self._from_dict(manifest, [])
119
+
120
+ def write_manifest(self, filepath):
121
+ '''
122
+ Writes the manifest to a file.
123
+
124
+ Args:
125
+ filename (filepath): Output filepath.
126
+
127
+ Examples:
128
+ >>> schema.write_manifest('mydump.json')
129
+ Dumps the current manifest into mydump.json
130
+ '''
131
+
132
+ fout = BaseSchema.__open_file(filepath, is_read=False)
133
+
134
+ if _has_orjson:
135
+ manifest_str = json.dumps(self.getdict(), option=json.OPT_INDENT_2).decode()
136
+ else:
137
+ manifest_str = json.dumps(self.getdict(), indent=2)
138
+ fout.write(manifest_str)
139
+
140
+ fout.close()
141
+
142
+ # Accessor methods
143
+ def __search(self,
144
+ *keypath,
145
+ insert_defaults=False,
146
+ use_default=False,
147
+ require_leaf=True,
148
+ complete_path=None):
149
+ if len(keypath) == 0:
150
+ if require_leaf:
151
+ raise KeyError
152
+ else:
153
+ return self
154
+
155
+ if complete_path is None:
156
+ complete_path = []
157
+ complete_path.append(keypath[0])
158
+
159
+ if keypath[0] == "default":
160
+ key_param = self.__default
161
+ else:
162
+ key_param = self.__manifest.get(keypath[0], None)
163
+ if not key_param:
164
+ if insert_defaults and self.__default:
165
+ if isinstance(self.__default, Parameter) and self.__default.get(field='lock'):
166
+ raise KeyError
167
+ key_param = self.__default.copy(key=complete_path)
168
+ self.__manifest[keypath[0]] = key_param
169
+ elif use_default and self.__default:
170
+ key_param = self.__default
171
+ else:
172
+ raise KeyError
173
+ if isinstance(key_param, BaseSchema):
174
+ if len(keypath) == 1:
175
+ if require_leaf:
176
+ raise KeyError
177
+ else:
178
+ return key_param
179
+ return key_param.__search(*keypath[1:],
180
+ insert_defaults=insert_defaults,
181
+ use_default=use_default,
182
+ require_leaf=require_leaf,
183
+ complete_path=complete_path)
184
+ return key_param
185
+
186
+ def get(self, *keypath, field='value', step=None, index=None):
187
+ """
188
+ Returns a parameter field from the schema.
189
+
190
+ Returns a schema parameter field based on the keypath provided in the
191
+ ``*keypath``. The returned type is consistent with the type field of the parameter.
192
+ Accessing a non-existent keypath raises a KeyError.
193
+
194
+ Args:
195
+ keypath (list of str): Keypath to access.
196
+ field (str): Parameter field to fetch, if None will return the :class:`Parameter`
197
+ object stored, if field is 'schema' the schema at this keypath will be returned.
198
+ step (str): Step name to access for parameters that may be specified
199
+ on a per-node basis.
200
+ index (str): Index name to access for parameters that may be specified
201
+ on a per-node basis.
202
+
203
+ Returns:
204
+ Value found for the keypath and field provided.
205
+
206
+ Examples:
207
+ >>> foundry = schema.get('pdk', 'virtual', 'foundry')
208
+ Returns the value of [pdk,virtual,foundry].
209
+ """
210
+
211
+ try:
212
+ require_leaf = True
213
+ if field == 'schema':
214
+ require_leaf = False
215
+ param = self.__search(
216
+ *keypath,
217
+ insert_defaults=False,
218
+ use_default=True,
219
+ require_leaf=require_leaf)
220
+ if field == 'schema':
221
+ if isinstance(param, Parameter):
222
+ raise ValueError(f"[{','.join(keypath)}] is a complete keypath")
223
+ return param
224
+ except KeyError:
225
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
226
+ if field is None:
227
+ return param
228
+ return param.get(field, step=step, index=index)
229
+
230
+ def set(self, *args, field='value', clobber=True, step=None, index=None):
231
+ '''
232
+ Sets a schema parameter field.
233
+
234
+ Sets a schema parameter field based on the keypath and value provided in
235
+ the ``*args``. New schema entries are automatically created for keypaths
236
+ that overlap with 'default' entries.
237
+
238
+ Args:
239
+ args (list): Parameter keypath followed by a value to set.
240
+ field (str): Parameter field to set.
241
+ clobber (bool): Existing value is overwritten if True.
242
+ step (str): Step name to set for parameters that may be specified
243
+ on a per-node basis.
244
+ index (str): Index name to set for parameters that may be specified
245
+ on a per-node basis.
246
+
247
+ Examples:
248
+ >>> schema.set('design', 'top')
249
+ Sets the [design] value to 'top'
250
+ '''
251
+
252
+ if len(args) < 2:
253
+ raise KeyError("keypath and value is required")
254
+
255
+ *keypath, value = args
256
+
257
+ try:
258
+ param = self.__search(*keypath, insert_defaults=True)
259
+ except KeyError:
260
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
261
+
262
+ return param.set(value, field=field, clobber=clobber, step=step, index=index)
263
+
264
+ def add(self, *args, field='value', step=None, index=None):
265
+ '''
266
+ Adds item(s) to a schema parameter list.
267
+
268
+ Adds item(s) to schema parameter list based on the keypath and value
269
+ provided in the ``*args``. New schema entries are automatically created
270
+ for keypaths that overlap with 'default' entries.
271
+
272
+ Args:
273
+ args (list): Parameter keypath followed by a value to add.
274
+ field (str): Parameter field to modify.
275
+ step (str): Step name to modify for parameters that may be specified
276
+ on a per-node basis.
277
+ index (str): Index name to modify for parameters that may be specified
278
+ on a per-node basis.
279
+
280
+ Examples:
281
+ >>> schema.add('input', 'rtl', 'verilog', 'hello.v')
282
+ Adds the file 'hello.v' to the [input,rtl,verilog] key.
283
+ '''
284
+
285
+ if len(args) < 2:
286
+ raise KeyError("keypath and value is required")
287
+
288
+ *keypath, value = args
289
+
290
+ try:
291
+ param = self.__search(*keypath, insert_defaults=True)
292
+ except KeyError:
293
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
294
+
295
+ return param.add(value, field=field, step=step, index=index)
296
+
297
+ def unset(self, *keypath, step=None, index=None):
298
+ '''
299
+ Unsets a schema parameter.
300
+
301
+ This method effectively undoes any previous calls to :meth:`set()` made to
302
+ the given keypath and step/index. For parameters with required or no
303
+ per-node values, unsetting a parameter always causes it to revert to its
304
+ default value, and future calls to :meth:`set()` with ``clobber=False`` will
305
+ once again be able to modify the value.
306
+
307
+ If you unset a particular step/index for a parameter with optional
308
+ per-node values, note that the newly returned value will be the global
309
+ value if it has been set. To completely return the parameter to its
310
+ default state, the global value has to be unset as well.
311
+
312
+ ``unset()`` has no effect if called on a parameter that has not been
313
+ previously set.
314
+
315
+ Args:
316
+ keypath (list): Parameter keypath to clear.
317
+ step (str): Step name to unset for parameters that may be specified
318
+ on a per-node basis.
319
+ index (str): Index name to unset for parameters that may be specified
320
+ on a per-node basis.
321
+ '''
322
+
323
+ try:
324
+ param = self.__search(*keypath, use_default=True)
325
+ except KeyError:
326
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
327
+
328
+ param.unset(step=step, index=index)
329
+
330
+ def remove(self, *keypath):
331
+ '''
332
+ Remove a schema parameter and its subparameters.
333
+
334
+ Args:
335
+ keypath (list): Parameter keypath to clear.
336
+ '''
337
+
338
+ search_path = keypath[0:-1]
339
+ removal_key = keypath[-1]
340
+ if removal_key == "default":
341
+ return
342
+
343
+ try:
344
+ key_param = self.__search(*search_path, require_leaf=False)
345
+ except KeyError:
346
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
347
+
348
+ if removal_key not in key_param.__manifest:
349
+ return
350
+
351
+ if not key_param.__default:
352
+ return
353
+
354
+ if any([key_param.get(*key, field='lock') for key in key_param.allkeys()]):
355
+ return
356
+
357
+ del key_param.__manifest[removal_key]
358
+
359
+ def valid(self, *keypath, default_valid=False, check_complete=False):
360
+ """
361
+ Checks validity of a keypath.
362
+
363
+ Checks the validity of a parameter keypath and returns True if the
364
+ keypath is valid and False if invalid.
365
+
366
+ Args:
367
+ keypath (list of str): keypath to check if valid.
368
+ default_valid (bool): Whether to consider "default" in valid
369
+ keypaths as a wildcard.
370
+ check_complete (bool): Require the keypath be a complete path.
371
+
372
+ Returns:
373
+ Boolean indicating validity of keypath.
374
+
375
+ Examples:
376
+ >>> check = schema.valid('design')
377
+ Returns True
378
+ >>> check = schema.valid('blah')
379
+ Returns False.
380
+ >>> check = schema.valid('metric', 'foo', '0', 'tasktime', default_valid=True)
381
+ Returns True, even if "foo" and "0" aren't in current configuration.
382
+ """
383
+
384
+ try:
385
+ param = self.__search(*keypath, use_default=default_valid, require_leaf=False)
386
+ except KeyError:
387
+ return False
388
+
389
+ if check_complete:
390
+ return isinstance(param, Parameter)
391
+ return True
392
+
393
+ def getkeys(self, *keypath):
394
+ """
395
+ Returns a tuple of schema dictionary keys.
396
+
397
+ Searches the schema for the keypath provided and returns a list of
398
+ keys found, excluding the generic 'default' key.
399
+
400
+ Args:
401
+ keypath (list of str): Keypath to get keys for.
402
+
403
+ Returns:
404
+ tuple of keys found for the keypath provided.
405
+
406
+ Examples:
407
+ >>> keylist = chip.getkeys('pdk')
408
+ Returns all keys for the [pdk] keypath.
409
+ """
410
+
411
+ if keypath:
412
+ try:
413
+ key_param = self.__search(*keypath, require_leaf=False)
414
+ except KeyError:
415
+ raise KeyError(f"[{','.join(keypath)}] is not a valid keypath")
416
+ if isinstance(key_param, Parameter):
417
+ return tuple()
418
+ else:
419
+ key_param = self
420
+
421
+ return tuple(key_param.__manifest.keys())
422
+
423
+ def allkeys(self, *keypath, include_default=True):
424
+ '''
425
+ Returns all keypaths in the schema as a set of tuples.
426
+
427
+ Arg:
428
+ keypath (list of str): Keypath prefix to search under. The
429
+ returned keypaths do not include the prefix.
430
+ '''
431
+
432
+ if keypath:
433
+ key_param = self.__manifest.get(keypath[0], None)
434
+ if not key_param or isinstance(key_param, Parameter):
435
+ return set()
436
+ return key_param.allkeys(*keypath[1:], include_default=include_default)
437
+
438
+ def add(keys, key, item):
439
+ if isinstance(item, Parameter):
440
+ keys.append((key,))
441
+ else:
442
+ for subkeypath in item.allkeys(include_default=include_default):
443
+ keys.append((key, *subkeypath))
444
+
445
+ keys = []
446
+ if include_default and self.__default:
447
+ add(keys, "default", self.__default)
448
+ for key, item in self.__manifest.items():
449
+ add(keys, key, item)
450
+ return set(keys)
451
+
452
+ def getdict(self, *keypath, include_default=True):
453
+ """
454
+ Returns a schema dictionary.
455
+
456
+ Searches the schema for the keypath provided and returns a complete
457
+ dictionary.
458
+
459
+ Args:
460
+ keypath (list of str): Variable length ordered schema key list
461
+ include_default (boolean): If true will include default key paths
462
+
463
+ Returns:
464
+ A schema dictionary
465
+
466
+ Examples:
467
+ >>> pdk = schema.getdict('pdk')
468
+ Returns the complete dictionary found for the keypath [pdk]
469
+ """
470
+
471
+ if keypath:
472
+ key_param = self.__manifest.get(keypath[0], None)
473
+ if not key_param:
474
+ return {}
475
+ return key_param.getdict(*keypath[1:], include_default=include_default)
476
+
477
+ manifest = {}
478
+ if include_default and self.__default:
479
+ manifest["default"] = self.__default.getdict(include_default=include_default)
480
+ for key, item in self.__manifest.items():
481
+ manifest[key] = item.getdict(include_default=include_default)
482
+ return manifest
483
+
484
+ # Utility functions
485
+ def copy(self, key=None):
486
+ """
487
+ Returns a copy of this schema.
488
+
489
+ Args:
490
+ key (list of str): keypath to this schema
491
+ """
492
+
493
+ return copy.deepcopy(self)