siliconcompiler 0.32.2__py3-none-any.whl → 0.33.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. siliconcompiler/__init__.py +19 -2
  2. siliconcompiler/_metadata.py +3 -2
  3. siliconcompiler/apps/sc.py +2 -2
  4. siliconcompiler/apps/sc_install.py +3 -3
  5. siliconcompiler/apps/sc_issue.py +1 -1
  6. siliconcompiler/apps/sc_remote.py +4 -4
  7. siliconcompiler/apps/sc_show.py +2 -2
  8. siliconcompiler/apps/utils/replay.py +5 -3
  9. siliconcompiler/asic.py +120 -0
  10. siliconcompiler/checklist.py +150 -0
  11. siliconcompiler/core.py +319 -345
  12. siliconcompiler/{templates → data/templates}/replay/replay.sh.j2 +2 -2
  13. siliconcompiler/flowgraph.py +803 -515
  14. siliconcompiler/fpga.py +84 -0
  15. siliconcompiler/metric.py +420 -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 +449 -0
  20. siliconcompiler/remote/client.py +61 -19
  21. siliconcompiler/remote/schema.py +116 -112
  22. siliconcompiler/remote/server.py +3 -5
  23. siliconcompiler/report/__init__.py +3 -2
  24. siliconcompiler/report/dashboard/__init__.py +61 -170
  25. siliconcompiler/report/dashboard/cli/__init__.py +79 -0
  26. siliconcompiler/report/dashboard/cli/board.py +895 -0
  27. siliconcompiler/report/dashboard/web/__init__.py +196 -0
  28. siliconcompiler/report/dashboard/{components → web/components}/__init__.py +9 -8
  29. siliconcompiler/report/dashboard/{components → web/components}/flowgraph.py +3 -3
  30. siliconcompiler/report/dashboard/{components → web/components}/graph.py +7 -4
  31. siliconcompiler/report/dashboard/{layouts → web/layouts}/__init__.py +3 -3
  32. siliconcompiler/report/dashboard/{layouts → web/layouts}/_common.py +1 -1
  33. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph.py +5 -5
  34. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph_node_tab.py +6 -6
  35. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph_sac_tabs.py +6 -6
  36. siliconcompiler/report/dashboard/{state.py → web/state.py} +1 -1
  37. siliconcompiler/report/dashboard/{utils → web/utils}/__init__.py +4 -3
  38. siliconcompiler/report/dashboard/{viewer.py → web/viewer.py} +4 -4
  39. siliconcompiler/report/html_report.py +2 -3
  40. siliconcompiler/report/report.py +13 -7
  41. siliconcompiler/report/summary_image.py +1 -1
  42. siliconcompiler/report/summary_table.py +3 -3
  43. siliconcompiler/report/utils.py +11 -10
  44. siliconcompiler/scheduler/__init__.py +153 -286
  45. siliconcompiler/scheduler/run_node.py +2 -1
  46. siliconcompiler/scheduler/send_messages.py +4 -4
  47. siliconcompiler/scheduler/slurm.py +2 -2
  48. siliconcompiler/schema/__init__.py +19 -2
  49. siliconcompiler/schema/baseschema.py +493 -0
  50. siliconcompiler/schema/cmdlineschema.py +250 -0
  51. siliconcompiler/{sphinx_ext → schema/docs}/__init__.py +3 -1
  52. siliconcompiler/{sphinx_ext → schema/docs}/dynamicgen.py +63 -81
  53. siliconcompiler/{sphinx_ext → schema/docs}/schemagen.py +73 -85
  54. siliconcompiler/{sphinx_ext → schema/docs}/utils.py +12 -13
  55. siliconcompiler/schema/editableschema.py +136 -0
  56. siliconcompiler/schema/journalingschema.py +238 -0
  57. siliconcompiler/schema/namedschema.py +41 -0
  58. siliconcompiler/schema/packageschema.py +101 -0
  59. siliconcompiler/schema/parameter.py +791 -0
  60. siliconcompiler/schema/parametertype.py +323 -0
  61. siliconcompiler/schema/parametervalue.py +736 -0
  62. siliconcompiler/schema/safeschema.py +37 -0
  63. siliconcompiler/schema/schema_cfg.py +109 -1789
  64. siliconcompiler/schema/utils.py +5 -68
  65. siliconcompiler/schema_obj.py +119 -0
  66. siliconcompiler/tool.py +1308 -0
  67. siliconcompiler/tools/_common/__init__.py +8 -10
  68. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +1 -1
  69. siliconcompiler/tools/bluespec/convert.py +7 -7
  70. siliconcompiler/tools/builtin/_common.py +1 -1
  71. siliconcompiler/tools/builtin/concatenate.py +2 -2
  72. siliconcompiler/tools/builtin/minimum.py +1 -1
  73. siliconcompiler/tools/builtin/mux.py +2 -1
  74. siliconcompiler/tools/builtin/nop.py +1 -1
  75. siliconcompiler/tools/builtin/verify.py +6 -4
  76. siliconcompiler/tools/chisel/convert.py +4 -4
  77. siliconcompiler/tools/genfasm/bitstream.py +3 -3
  78. siliconcompiler/tools/ghdl/convert.py +1 -1
  79. siliconcompiler/tools/icarus/compile.py +4 -4
  80. siliconcompiler/tools/icepack/bitstream.py +6 -1
  81. siliconcompiler/tools/klayout/convert_drc_db.py +5 -0
  82. siliconcompiler/tools/klayout/klayout_export.py +0 -1
  83. siliconcompiler/tools/klayout/klayout_utils.py +3 -10
  84. siliconcompiler/tools/nextpnr/apr.py +6 -1
  85. siliconcompiler/tools/nextpnr/nextpnr.py +4 -4
  86. siliconcompiler/tools/openroad/_apr.py +17 -0
  87. siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -14
  88. siliconcompiler/tools/openroad/rdlroute.py +3 -3
  89. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +1 -1
  90. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +5 -5
  91. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +3 -3
  92. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +3 -3
  93. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +3 -3
  94. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +3 -3
  95. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +3 -3
  96. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +3 -3
  97. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +4 -4
  98. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +3 -3
  99. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +3 -3
  100. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +3 -3
  101. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +4 -4
  102. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +3 -3
  103. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +3 -3
  104. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +3 -3
  105. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +3 -3
  106. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +4 -4
  107. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +3 -3
  108. siliconcompiler/tools/openroad/scripts/common/procs.tcl +58 -2
  109. siliconcompiler/tools/openroad/scripts/common/reports.tcl +2 -2
  110. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +2 -2
  111. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -3
  112. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +2 -2
  113. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +4 -4
  114. siliconcompiler/tools/openroad/scripts/sc_show.tcl +7 -7
  115. siliconcompiler/tools/opensta/__init__.py +1 -1
  116. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +1 -1
  117. siliconcompiler/tools/opensta/scripts/sc_procs.tcl +16 -0
  118. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +1 -1
  119. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +35 -7
  120. siliconcompiler/tools/opensta/timing.py +6 -2
  121. siliconcompiler/tools/slang/__init__.py +10 -10
  122. siliconcompiler/tools/surelog/parse.py +4 -4
  123. siliconcompiler/tools/sv2v/convert.py +20 -3
  124. siliconcompiler/tools/verilator/compile.py +2 -2
  125. siliconcompiler/tools/verilator/verilator.py +3 -3
  126. siliconcompiler/tools/vpr/place.py +1 -1
  127. siliconcompiler/tools/vpr/route.py +4 -4
  128. siliconcompiler/tools/vpr/screenshot.py +1 -1
  129. siliconcompiler/tools/vpr/show.py +5 -5
  130. siliconcompiler/tools/vpr/vpr.py +24 -24
  131. siliconcompiler/tools/xdm/convert.py +2 -2
  132. siliconcompiler/tools/xyce/simulate.py +1 -1
  133. siliconcompiler/tools/yosys/sc_synth_asic.tcl +104 -90
  134. siliconcompiler/tools/yosys/syn_asic.py +13 -4
  135. siliconcompiler/toolscripts/_tools.json +12 -7
  136. siliconcompiler/toolscripts/rhel8/install-chisel.sh +2 -0
  137. siliconcompiler/toolscripts/rhel8/install-icarus.sh +1 -0
  138. siliconcompiler/toolscripts/rhel8/install-klayout.sh +2 -0
  139. siliconcompiler/toolscripts/rhel8/install-magic.sh +1 -2
  140. siliconcompiler/toolscripts/rhel8/install-netgen.sh +1 -1
  141. siliconcompiler/toolscripts/rhel8/install-slang.sh +2 -0
  142. siliconcompiler/toolscripts/rhel8/install-surelog.sh +3 -1
  143. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +1 -0
  144. siliconcompiler/toolscripts/rhel8/install-verible.sh +2 -0
  145. siliconcompiler/toolscripts/rhel8/install-verilator.sh +1 -0
  146. siliconcompiler/toolscripts/rhel8/install-xyce.sh +2 -0
  147. siliconcompiler/toolscripts/rhel9/install-chisel.sh +2 -0
  148. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +1 -0
  149. siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +1 -0
  150. siliconcompiler/toolscripts/rhel9/install-icarus.sh +1 -0
  151. siliconcompiler/toolscripts/rhel9/install-klayout.sh +2 -0
  152. siliconcompiler/toolscripts/rhel9/install-magic.sh +1 -2
  153. siliconcompiler/toolscripts/rhel9/install-netgen.sh +1 -1
  154. siliconcompiler/toolscripts/rhel9/install-openroad.sh +2 -0
  155. siliconcompiler/toolscripts/rhel9/install-opensta.sh +76 -0
  156. siliconcompiler/toolscripts/rhel9/install-slang.sh +3 -1
  157. siliconcompiler/toolscripts/rhel9/install-surelog.sh +2 -1
  158. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +1 -0
  159. siliconcompiler/toolscripts/rhel9/install-verible.sh +2 -0
  160. siliconcompiler/toolscripts/rhel9/install-verilator.sh +1 -0
  161. siliconcompiler/toolscripts/rhel9/install-vpr.sh +2 -0
  162. siliconcompiler/toolscripts/rhel9/install-xdm.sh +2 -0
  163. siliconcompiler/toolscripts/rhel9/install-xyce.sh +2 -0
  164. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +2 -0
  165. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +2 -0
  166. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +3 -1
  167. siliconcompiler/toolscripts/rhel9/install-yosys.sh +2 -0
  168. siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +2 -0
  169. siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +2 -0
  170. siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +2 -0
  171. siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +2 -0
  172. siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +2 -0
  173. siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +2 -0
  174. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +2 -0
  175. siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +2 -0
  176. siliconcompiler/toolscripts/ubuntu20/install-magic.sh +2 -0
  177. siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +2 -0
  178. siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +1 -3
  179. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +2 -0
  180. siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +72 -0
  181. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +3 -1
  182. siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +2 -0
  183. siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +3 -1
  184. siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +1 -1
  185. siliconcompiler/toolscripts/ubuntu20/install-verible.sh +2 -0
  186. siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +2 -0
  187. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +2 -0
  188. siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +2 -0
  189. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +2 -0
  190. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +2 -0
  191. siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +2 -0
  192. siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +2 -0
  193. siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +2 -0
  194. siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +2 -0
  195. siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +2 -0
  196. siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +2 -0
  197. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +2 -0
  198. siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +2 -0
  199. siliconcompiler/toolscripts/ubuntu22/install-magic.sh +2 -0
  200. siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +2 -0
  201. siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +1 -2
  202. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +2 -0
  203. siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +72 -0
  204. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +3 -1
  205. siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +2 -0
  206. siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +3 -1
  207. siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +1 -1
  208. siliconcompiler/toolscripts/ubuntu22/install-verible.sh +2 -0
  209. siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +2 -0
  210. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +2 -2
  211. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +2 -0
  212. siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +2 -0
  213. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +2 -0
  214. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +2 -0
  215. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +3 -1
  216. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +2 -0
  217. siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +2 -0
  218. siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +2 -0
  219. siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +2 -0
  220. siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +2 -0
  221. siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +2 -0
  222. siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +2 -0
  223. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +2 -0
  224. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +2 -0
  225. siliconcompiler/toolscripts/ubuntu24/install-magic.sh +2 -0
  226. siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +2 -0
  227. siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +1 -3
  228. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +2 -0
  229. siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +72 -0
  230. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +3 -1
  231. siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +2 -0
  232. siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +3 -1
  233. siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +1 -1
  234. siliconcompiler/toolscripts/ubuntu24/install-verible.sh +2 -0
  235. siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +2 -0
  236. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +2 -2
  237. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +2 -0
  238. siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +2 -0
  239. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +2 -0
  240. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +2 -0
  241. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +3 -1
  242. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +2 -0
  243. siliconcompiler/utils/__init__.py +8 -112
  244. siliconcompiler/utils/flowgraph.py +339 -0
  245. siliconcompiler/{issue.py → utils/issue.py} +7 -4
  246. siliconcompiler/utils/logging.py +86 -33
  247. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.33.0.dist-info}/METADATA +10 -8
  248. siliconcompiler-0.33.0.dist-info/RECORD +487 -0
  249. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.33.0.dist-info}/WHEEL +1 -1
  250. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.33.0.dist-info}/entry_points.txt +8 -8
  251. siliconcompiler/schema/schema_obj.py +0 -1936
  252. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +0 -27
  253. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +0 -59
  254. siliconcompiler-0.32.2.dist-info/RECORD +0 -464
  255. /siliconcompiler/{templates → data/templates}/__init__.py +0 -0
  256. /siliconcompiler/{templates → data/templates}/email/__init__.py +0 -0
  257. /siliconcompiler/{templates → data/templates}/email/general.j2 +0 -0
  258. /siliconcompiler/{templates → data/templates}/email/summary.j2 +0 -0
  259. /siliconcompiler/{templates → data/templates}/issue/README.txt +0 -0
  260. /siliconcompiler/{templates → data/templates}/issue/__init__.py +0 -0
  261. /siliconcompiler/{templates → data/templates}/issue/run.sh +0 -0
  262. /siliconcompiler/{templates → data/templates}/replay/replay.py.j2 +0 -0
  263. /siliconcompiler/{templates → data/templates}/replay/requirements.txt +0 -0
  264. /siliconcompiler/{templates → data/templates}/replay/setup.sh +0 -0
  265. /siliconcompiler/{templates → data/templates}/report/__init__.py +0 -0
  266. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.css +0 -0
  267. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.js +0 -0
  268. /siliconcompiler/{templates → data/templates}/report/bootstrap_LICENSE.md +0 -0
  269. /siliconcompiler/{templates → data/templates}/report/sc_report.j2 +0 -0
  270. /siliconcompiler/{templates → data/templates}/slurm/__init__.py +0 -0
  271. /siliconcompiler/{templates → data/templates}/slurm/run.sh +0 -0
  272. /siliconcompiler/{templates → data/templates}/tcl/__init__.py +0 -0
  273. /siliconcompiler/{templates → data/templates}/tcl/manifest.tcl.j2 +0 -0
  274. /siliconcompiler/report/dashboard/{utils → web/utils}/file_utils.py +0 -0
  275. /siliconcompiler/{units.py → utils/units.py} +0 -0
  276. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.33.0.dist-info}/licenses/LICENSE +0 -0
  277. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.33.0.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,8 @@
1
1
  import contextlib
2
- import distro
3
- import getpass
4
2
  import multiprocessing
5
3
  import logging
6
4
  import os
7
- import platform
8
5
  import psutil
9
- import socket
10
6
  import re
11
7
  import shlex
12
8
  import shutil
@@ -17,24 +13,25 @@ import packaging.version
17
13
  import packaging.specifiers
18
14
  from io import StringIO
19
15
  import traceback
20
- from datetime import datetime
21
16
  from logging.handlers import QueueHandler, QueueListener
22
17
  from siliconcompiler import sc_open
23
18
  from siliconcompiler import utils
24
- from siliconcompiler import _metadata
25
19
  from siliconcompiler.remote import Client
26
- from siliconcompiler.schema import Schema
20
+ from siliconcompiler import Schema
21
+ from siliconcompiler.schema import JournalingSchema
22
+ from siliconcompiler.record import RecordTime, RecordTool
27
23
  from siliconcompiler.scheduler import slurm
28
24
  from siliconcompiler.scheduler import docker_runner
29
25
  from siliconcompiler import NodeStatus, SiliconCompilerError
30
- from siliconcompiler.flowgraph import _get_flowgraph_nodes, _get_flowgraph_execution_order, \
31
- _get_pruned_node_inputs, _get_flowgraph_entry_nodes, \
32
- _unreachable_steps_to_execute, _nodes_to_execute, \
26
+ from siliconcompiler.utils.flowgraph import _get_flowgraph_execution_order, \
27
+ _get_pruned_node_inputs, \
33
28
  get_nodes_from, nodes_to_execute, _check_flowgraph
29
+ from siliconcompiler.utils.logging import SCBlankLoggerFormatter
34
30
  from siliconcompiler.tools._common import input_file_node_name
35
31
  import lambdapdk
36
32
  from siliconcompiler.tools._common import get_tool_task, record_metric
37
33
  from siliconcompiler.scheduler import send_messages
34
+ from siliconcompiler.flowgraph import RuntimeFlowgraph
38
35
 
39
36
  try:
40
37
  import resource
@@ -60,6 +57,14 @@ def _get_callback(hook):
60
57
  _failed_log_lines = 20
61
58
 
62
59
 
60
+ #######################################
61
+ def _do_record_access():
62
+ '''
63
+ Determine if Schema should record calls to .get
64
+ '''
65
+ return False
66
+
67
+
63
68
  ###############################################################################
64
69
  class SiliconCompilerTimeout(Exception):
65
70
  ''' Minimal Exception wrapper used to raise sc timeout errors.
@@ -87,6 +92,8 @@ def run(chip):
87
92
 
88
93
  # Re-init logger to include run info after setting up flowgraph.
89
94
  chip._init_logger(in_run=True)
95
+ if chip._dash and not chip._dash.is_running():
96
+ chip._dash.open_dashboard()
90
97
 
91
98
  # Check if flowgraph is complete and valid
92
99
  flow = chip.get('option', 'flow')
@@ -98,7 +105,7 @@ def run(chip):
98
105
  copy_old_run_dir(chip, org_jobname)
99
106
  clean_build_dir(chip)
100
107
  _reset_flow_nodes(chip, flow, nodes_to_execute(chip, flow))
101
- __record_packages(chip)
108
+ chip.schema.get("record", field='schema').record_python_packages()
102
109
 
103
110
  if chip.get('option', 'remote'):
104
111
  client = Client(chip)
@@ -130,10 +137,6 @@ def _finalize_run(chip):
130
137
  filepath = os.path.join(chip.getworkdir(), f"{chip.design}.pkg.json")
131
138
  chip.write_manifest(filepath)
132
139
 
133
- # Update dashboard
134
- if chip._dash:
135
- chip._dash.update_manifest()
136
-
137
140
  send_messages.send(chip, 'summary', None, None)
138
141
 
139
142
 
@@ -176,18 +179,17 @@ def _local_process(chip, flow):
176
179
  extra_setup_nodes = {}
177
180
 
178
181
  if chip.get('option', 'clean') or not chip.get('option', 'from'):
179
- load_nodes = _get_flowgraph_nodes(chip, flow)
182
+ load_nodes = list(chip.schema.get("flowgraph", flow, field="schema").get_nodes())
180
183
  else:
181
184
  for step in chip.get('option', 'from'):
182
185
  from_nodes.extend(
183
186
  [(step, index) for index in chip.getkeys('flowgraph', flow, step)])
184
187
 
185
- load_nodes = _nodes_to_execute(
186
- chip,
187
- flow,
188
- _get_flowgraph_entry_nodes(chip, flow),
189
- from_nodes,
190
- chip.get('option', 'prune'))
188
+ runtime = RuntimeFlowgraph(
189
+ chip.schema.get("flowgraph", flow, field="schema"),
190
+ to_steps=chip.get('option', 'from'),
191
+ prune_nodes=chip.get('option', 'prune'))
192
+ load_nodes = list(runtime.get_nodes())
191
193
 
192
194
  for node_level in _get_flowgraph_execution_order(chip, flow):
193
195
  for step, index in node_level:
@@ -202,12 +204,14 @@ def _local_process(chip, flow):
202
204
  if os.path.exists(manifest):
203
205
  # ensure we setup these nodes again
204
206
  try:
205
- extra_setup_nodes[(step, index)] = Schema(manifest=manifest, logger=chip.logger)
207
+ journal = JournalingSchema(Schema())
208
+ journal.read_manifest(manifest)
209
+ extra_setup_nodes[(step, index)] = journal
206
210
  except Exception:
207
211
  pass
208
212
 
209
213
  # Setup tools for all nodes to run.
210
- nodes = nodes_to_execute(chip, flow)
214
+ nodes = list(nodes_to_execute(chip, flow))
211
215
  all_setup_nodes = nodes + load_nodes + list(extra_setup_nodes.keys())
212
216
  for layer_nodes in _get_flowgraph_execution_order(chip, flow):
213
217
  for step, index in layer_nodes:
@@ -223,19 +227,28 @@ def _local_process(chip, flow):
223
227
  except: # noqa E722
224
228
  pass
225
229
  if node_status:
226
- chip.set('record', 'status', node_status, step=step, index=index)
230
+ chip.schema.get("record", field='schema').set('status', node_status,
231
+ step=step, index=index)
227
232
 
228
233
  def mark_pending(step, index):
229
- chip.set('record', 'status', NodeStatus.PENDING, step=step, index=index)
234
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
235
+ step=step, index=index)
230
236
  for next_step, next_index in get_nodes_from(chip, flow, [(step, index)]):
231
237
  if chip.get('record', 'status', step=next_step, index=next_index) == \
232
238
  NodeStatus.SKIPPED:
233
239
  continue
234
240
 
235
241
  # Mark following steps as pending
236
- chip.set('record', 'status', NodeStatus.PENDING, step=next_step, index=next_index)
242
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
243
+ step=next_step, index=next_index)
237
244
 
238
245
  # Check if nodes have been modified from previous data
246
+ runtimeflow = RuntimeFlowgraph(
247
+ chip.schema.get("flowgraph", flow, field="schema"),
248
+ from_steps=chip.get('option', 'from'),
249
+ to_steps=chip.get('option', 'to'),
250
+ prune_nodes=chip.get('option', 'prune'))
251
+
239
252
  for layer_nodes in _get_flowgraph_execution_order(chip, flow):
240
253
  for step, index in layer_nodes:
241
254
  # Only look at successful nodes
@@ -243,12 +256,14 @@ def _local_process(chip, flow):
243
256
  (NodeStatus.SUCCESS, NodeStatus.SKIPPED):
244
257
  continue
245
258
 
246
- if not check_node_inputs(chip, step, index):
259
+ if (step, index) in runtimeflow.get_nodes() and \
260
+ not check_node_inputs(chip, step, index):
247
261
  # change failing nodes to pending
248
262
  mark_pending(step, index)
249
263
  elif (step, index) in extra_setup_nodes:
250
264
  # import old information
251
- chip.schema._import_journal(extra_setup_nodes[(step, index)])
265
+ JournalingSchema(chip.schema).import_journal(
266
+ schema=extra_setup_nodes[(step, index)])
252
267
 
253
268
  # Ensure pending nodes cause following nodes to be run
254
269
  for step, index in nodes:
@@ -281,7 +296,7 @@ def _local_process(chip, flow):
281
296
 
282
297
  # Handle logs across threads
283
298
  log_listener = QueueListener(log_queue, chip.logger._console)
284
- chip.logger._console.setFormatter(logging.Formatter("%(message)s"))
299
+ chip.logger._console.setFormatter(SCBlankLoggerFormatter())
285
300
  log_listener.start()
286
301
 
287
302
  # Update dashboard before run begins
@@ -345,7 +360,8 @@ def _setup_node(chip, step, index, flow=None):
345
360
 
346
361
  if setup_ret is not None:
347
362
  chip.logger.warning(f'Removing {step}{index} due to {setup_ret}')
348
- chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
363
+ chip.schema.get("record", field='schema').set('status', NodeStatus.SKIPPED,
364
+ step=step, index=index)
349
365
 
350
366
  return False
351
367
 
@@ -458,17 +474,17 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
458
474
  chip.set('arg', 'step', step, clobber=True)
459
475
  chip.set('arg', 'index', index, clobber=True)
460
476
 
461
- chip.schema._start_journal()
477
+ chip.schema = JournalingSchema(chip.schema)
478
+ chip.schema.start_journal()
462
479
 
463
480
  # Make record of sc version and machine
464
- __record_version(chip, step, index)
481
+ chip.schema.get("record", field='schema').record_version(step, index)
465
482
  # Record user information if enabled
466
483
  if chip.get('option', 'track', step=step, index=index):
467
- __record_usermachine(chip, step, index)
484
+ chip.schema.get("record", field='schema').record_userinformation(step, index)
468
485
 
469
486
  # Start wall timer
470
- wall_start = time.time()
471
- __record_time(chip, step, index, wall_start, 'start')
487
+ chip.schema.get("record", field='schema').record_time(step, index, RecordTime.START)
472
488
 
473
489
  workdir = _setup_workdir(chip, step, index, replay)
474
490
  cwd = os.getcwd()
@@ -486,7 +502,8 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
486
502
 
487
503
  # return to original directory
488
504
  os.chdir(cwd)
489
- chip.schema._stop_journal()
505
+ chip.schema.stop_journal()
506
+ chip.schema = chip.schema.get_base_schema()
490
507
 
491
508
  if pipe:
492
509
  pipe.send(chip._packages)
@@ -494,7 +511,8 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
494
511
 
495
512
  ###########################################################################
496
513
  def _haltstep(chip, flow, step, index, log=True):
497
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
514
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
515
+ step=step, index=index)
498
516
  chip.write_manifest(os.path.join("outputs", f"{chip.get('design')}.pkg.json"))
499
517
 
500
518
  if log:
@@ -567,12 +585,14 @@ def _select_inputs(chip, step, index, trial=False):
567
585
  else:
568
586
  sel_inputs = _get_pruned_node_inputs(chip, flow, (step, index))
569
587
 
570
- if (step, index) not in _get_flowgraph_entry_nodes(chip, flow) and not sel_inputs:
588
+ if (step, index) not in chip.schema.get("flowgraph", flow, field="schema").get_entry_nodes() \
589
+ and not sel_inputs:
571
590
  chip.logger.error(f'No inputs selected after running {tool}')
572
591
  _haltstep(chip, flow, step, index)
573
592
 
574
593
  if not trial:
575
- chip.set('record', 'inputnode', sel_inputs, step=step, index=index)
594
+ chip.schema.get("record", field='schema').set('inputnode', sel_inputs,
595
+ step=step, index=index)
576
596
 
577
597
  return sel_inputs
578
598
 
@@ -662,15 +682,15 @@ def __read_std_streams(chip, quiet,
662
682
  # Chip helper Functions
663
683
  ############################################################################
664
684
  def _getexe(chip, tool, step, index):
665
- path = chip.get('tool', tool, 'path', step=step, index=index)
666
685
  exe = chip.get('tool', tool, 'exe')
667
686
  if exe is None:
668
687
  return None
688
+ path = chip.find_files('tool', tool, 'path', step=step, index=index)
669
689
 
670
690
  syspath = os.getenv('PATH', os.defpath)
671
691
  if path:
672
692
  # Prepend 'path' schema var to system path
673
- syspath = utils._resolve_env_vars(chip, path, step, index) + os.pathsep + syspath
693
+ syspath = path + os.pathsep + syspath
674
694
 
675
695
  fullexe = shutil.which(exe, path=syspath)
676
696
 
@@ -715,20 +735,12 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
715
735
 
716
736
  fullexe = _getexe(chip, tool, step, index)
717
737
 
718
- is_posix = __is_posix()
719
-
720
738
  def parse_options(options):
721
739
  if not options:
722
740
  return []
723
741
  shlex_opts = []
724
742
  for option in options:
725
- option = option.strip()
726
- if (option.startswith("\"") and option.endswith("\"")) or \
727
- (option.startswith("'") and option.endswith("'")):
728
- # Make sure strings are quoted in double quotes
729
- shlex_opts.append(f'"{option[1:-1]}"')
730
- else:
731
- shlex_opts.extend(shlex.split(option, posix=is_posix))
743
+ shlex_opts.append(str(option).strip())
732
744
  return shlex_opts
733
745
 
734
746
  # Add scripts files
@@ -744,9 +756,10 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
744
756
  runtime_options = getattr(chip._get_tool_module(step, index), 'runtime_options', None)
745
757
  if runtime_options:
746
758
  try:
747
- chip.schema._start_record_access()
759
+ if _do_record_access():
760
+ chip.schema.add_journaling_type("get")
748
761
  cmdlist.extend(parse_options(runtime_options(chip)))
749
- chip.schema._stop_record_access()
762
+ chip.schema.remove_journaling_type("get")
750
763
  except Exception as e:
751
764
  chip.logger.error(f'Failed to get runtime options for {tool}/{task}')
752
765
  raise e
@@ -754,14 +767,7 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
754
767
  # Separate variables to be able to display nice name of executable
755
768
  cmd = os.path.basename(cmdlist[0])
756
769
  cmd_args = cmdlist[1:]
757
- print_cmd = " ".join([cmd, *cmd_args])
758
- cmdlist = [cmdlist[0]]
759
- for arg in cmd_args:
760
- if arg.startswith("\"") and arg.endswith("\""):
761
- # Remove quoting since subprocess will handle that for us
762
- cmdlist.append(arg[1:-1])
763
- else:
764
- cmdlist.append(arg)
770
+ print_cmd = shlex.join([cmd, *cmd_args])
765
771
 
766
772
  # create replay file
767
773
  with open(script_name, 'w') as f:
@@ -794,9 +800,9 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
794
800
  add_new_line = True
795
801
 
796
802
  if add_new_line:
797
- format_cmd.append(cmdarg)
803
+ format_cmd.append(shlex.quote(cmdarg))
798
804
  else:
799
- format_cmd[-1] += f' {cmdarg}'
805
+ format_cmd[-1] += f' {shlex.quote(cmdarg)}'
800
806
 
801
807
  replay_opts["cmds"] = format_cmd
802
808
 
@@ -916,9 +922,8 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
916
922
  ##################
917
923
  # Make record of tool options
918
924
  if cmd_args is not None:
919
- chip.set('record', 'toolargs',
920
- ' '.join(f'"{arg}"' if ' ' in arg else arg for arg in cmd_args),
921
- step=step, index=index)
925
+ chip.schema.get("record", field='schema').record_tool(
926
+ step, index, cmd_args, RecordTool.ARGS)
922
927
 
923
928
  chip.logger.info('%s', printable_cmd)
924
929
  timeout = chip.get('option', 'timeout', step=step, index=index)
@@ -963,7 +968,6 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
963
968
  if nice:
964
969
  preexec_fn = set_nice
965
970
 
966
- cmd_start_time = time.time()
967
971
  proc = subprocess.Popen(cmdlist,
968
972
  stdin=subprocess.DEVNULL,
969
973
  stdout=stdout_writer,
@@ -1005,7 +1009,7 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
1005
1009
  is_stdout_log, stdout_reader, stdout_print,
1006
1010
  is_stderr_log, stderr_reader, stderr_print)
1007
1011
 
1008
- if timeout is not None and time.time() - cmd_start_time > timeout:
1012
+ if timeout is not None and time.time() - cpu_start > timeout:
1009
1013
  chip.logger.error(f'Step timed out after {timeout} seconds')
1010
1014
  utils.terminate_process(proc.pid)
1011
1015
  raise SiliconCompilerTimeout(f'{step}{index} timeout')
@@ -1025,7 +1029,7 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
1025
1029
  is_stderr_log, stderr_reader, stderr_print)
1026
1030
  retcode = proc.returncode
1027
1031
 
1028
- chip.set('record', 'toolexitcode', retcode, step=step, index=index)
1032
+ chip.schema.get("record", field='schema').record_tool(step, index, retcode, RecordTool.EXITCODE)
1029
1033
  if retcode != 0:
1030
1034
  msg = f'Command failed with code {retcode}.'
1031
1035
  if logfile:
@@ -1057,9 +1061,10 @@ def _post_process(chip, step, index):
1057
1061
  func = getattr(chip._get_task_module(step, index, flow=flow), 'post_process', None)
1058
1062
  if func:
1059
1063
  try:
1060
- chip.schema._start_record_access()
1064
+ if _do_record_access():
1065
+ chip.schema.add_journaling_type("get")
1061
1066
  func(chip)
1062
- chip.schema._stop_record_access()
1067
+ chip.schema.remove_journaling_type("get")
1063
1068
  except Exception as e:
1064
1069
  chip.logger.error(f'Failed to run post-process for {tool}/{task}.')
1065
1070
  print_traceback(chip, e)
@@ -1124,10 +1129,12 @@ def _executenode(chip, step, index, replay):
1124
1129
  toolpath, version = _check_tool_version(chip, step, index, run_func)
1125
1130
 
1126
1131
  if version:
1127
- chip.set('record', 'toolversion', version, step=step, index=index)
1132
+ chip.schema.get("record", field='schema').record_tool(
1133
+ step, index, version, RecordTool.VERSION)
1128
1134
 
1129
1135
  if toolpath:
1130
- chip.set('record', 'toolpath', toolpath, step=step, index=index)
1136
+ chip.schema.get("record", field='schema').record_tool(
1137
+ step, index, toolpath, RecordTool.PATH)
1131
1138
 
1132
1139
  # Write manifest (tool interface) (Don't move this!)
1133
1140
  _write_task_manifest(chip, tool)
@@ -1152,9 +1159,10 @@ def _pre_process(chip, step, index):
1152
1159
  func = getattr(chip._get_task_module(step, index, flow=flow), 'pre_process', None)
1153
1160
  if func:
1154
1161
  try:
1155
- chip.schema._start_record_access()
1162
+ if _do_record_access():
1163
+ chip.schema.add_journaling_type("get")
1156
1164
  func(chip)
1157
- chip.schema._stop_record_access()
1165
+ chip.schema.remove_journaling_type("get")
1158
1166
  except Exception as e:
1159
1167
  chip.logger.error(f"Pre-processing failed for '{tool}/{task}'.")
1160
1168
  raise e
@@ -1168,11 +1176,10 @@ def _set_env_vars(chip, step, index):
1168
1176
 
1169
1177
  tool, task = get_tool_task(chip, step, index)
1170
1178
 
1171
- chip.schema._start_record_access()
1172
-
1179
+ if _do_record_access():
1180
+ chip.schema.add_journaling_type("get")
1173
1181
  os.environ.update(_get_run_env_vars(chip, tool, task, step, index, include_path=True))
1174
-
1175
- chip.schema._stop_record_access()
1182
+ chip.schema.remove_journaling_type("get")
1176
1183
 
1177
1184
  return org_env
1178
1185
 
@@ -1266,7 +1273,8 @@ def _hash_files(chip, step, index, setup=False):
1266
1273
 
1267
1274
 
1268
1275
  def _finalizenode(chip, step, index, replay):
1269
- if chip.schema._do_record_access():
1276
+ if chip.schema.is_journaling() and any(
1277
+ [record["type"] == "get" for record in chip.schema.get_journal()]):
1270
1278
  assert_required_accesses(chip, step, index)
1271
1279
 
1272
1280
  flow = chip.get('option', 'flow')
@@ -1291,12 +1299,11 @@ def _finalizenode(chip, step, index, replay):
1291
1299
  _hash_files(chip, step, index)
1292
1300
 
1293
1301
  # Capture wall runtime and cpu cores
1294
- wall_end = time.time()
1295
- __record_time(chip, step, index, wall_end, 'end')
1302
+ end_time = chip.schema.get("record", field='schema').record_time(step, index, RecordTime.END)
1296
1303
 
1297
1304
  # calculate total time
1298
1305
  total_times = []
1299
- for check_step, check_index in _get_flowgraph_nodes(chip, flow):
1306
+ for check_step, check_index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1300
1307
  total_time = chip.get('metric', 'totaltime', step=check_step, index=check_index)
1301
1308
  if total_time is not None:
1302
1309
  total_times.append(total_time)
@@ -1305,7 +1312,8 @@ def _finalizenode(chip, step, index, replay):
1305
1312
  else:
1306
1313
  total_time = 0.0
1307
1314
 
1308
- walltime = wall_end - get_record_time(chip, step, index, 'starttime')
1315
+ walltime = end_time - chip.schema.get("record", field='schema').get_recorded_time(
1316
+ step, index, RecordTime.START)
1309
1317
  record_metric(chip, step, index, 'tasktime', walltime,
1310
1318
  source=None, source_unit='s')
1311
1319
  record_metric(chip, step, index, 'totaltime', total_time + walltime,
@@ -1314,7 +1322,9 @@ def _finalizenode(chip, step, index, replay):
1314
1322
 
1315
1323
  # Save a successful manifest
1316
1324
  if not is_skipped:
1317
- chip.set('record', 'status', NodeStatus.SUCCESS, step=step, index=index)
1325
+ chip.schema.get("record", field='schema').set('status', NodeStatus.SUCCESS,
1326
+ step=step, index=index)
1327
+
1318
1328
  chip.write_manifest(os.path.join("outputs", f"{chip.get('design')}.pkg.json"))
1319
1329
 
1320
1330
  if chip._error and not replay:
@@ -1336,7 +1346,7 @@ def _finalizenode(chip, step, index, replay):
1336
1346
 
1337
1347
  def _make_testcase(chip, step, index):
1338
1348
  # Import here to avoid circular import
1339
- from siliconcompiler.issue import generate_testcase
1349
+ from siliconcompiler.utils.issue import generate_testcase
1340
1350
 
1341
1351
  generate_testcase(
1342
1352
  chip,
@@ -1379,7 +1389,8 @@ def assert_required_accesses(chip, step, index):
1379
1389
  if tool == 'builtin':
1380
1390
  return
1381
1391
 
1382
- gets = chip.schema._get_record_access()
1392
+ gets = set([tuple(record["key"]) for record in chip.schema.get_journal()
1393
+ if record["type"] == "get"])
1383
1394
  logfile = os.path.join(
1384
1395
  chip.getworkdir(jobname=jobname, step=step, index=index),
1385
1396
  f'{step}.log')
@@ -1458,20 +1469,20 @@ def _reset_flow_nodes(chip, flow, nodes_to_execute):
1458
1469
 
1459
1470
  def clear_node(step, index):
1460
1471
  # Reset metrics and records
1472
+ chip.schema.get("metric", field='schema').clear(step, index)
1461
1473
  for metric in chip.getkeys('metric'):
1462
1474
  _clear_metric(chip, step, index, metric)
1463
- for record in chip.getkeys('record'):
1464
- _clear_record(chip, step, index, record, preserve=[
1465
- 'remoteid',
1466
- 'status',
1467
- 'pythonpackage'])
1475
+
1476
+ chip.schema.get("record", field='schema').clear(
1477
+ step, index, keep=['remoteid', 'status', 'pythonpackage'])
1468
1478
 
1469
1479
  # Mark all nodes as pending
1470
- for step, index in _get_flowgraph_nodes(chip, flow):
1471
- chip.set('record', 'status', NodeStatus.PENDING, step=step, index=index)
1480
+ for step, index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1481
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
1482
+ step=step, index=index)
1472
1483
 
1473
1484
  should_resume = not chip.get('option', 'clean')
1474
- for step, index in _get_flowgraph_nodes(chip, flow):
1485
+ for step, index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1475
1486
  stepdir = chip.getworkdir(step=step, index=index)
1476
1487
  cfg = f"{stepdir}/outputs/{chip.get('design')}.pkg.json"
1477
1488
 
@@ -1485,12 +1496,14 @@ def _reset_flow_nodes(chip, flow, nodes_to_execute):
1485
1496
  try:
1486
1497
  old_status = Schema(manifest=cfg).get('record', 'status', step=step, index=index)
1487
1498
  if old_status:
1488
- chip.set('record', 'status', old_status, step=step, index=index)
1499
+ chip.schema.get("record", field='schema').set('status', old_status,
1500
+ step=step, index=index)
1489
1501
  except Exception:
1490
1502
  # unable to load so leave it default
1491
1503
  pass
1492
1504
  else:
1493
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1505
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1506
+ step=step, index=index)
1494
1507
 
1495
1508
  for step in chip.getkeys('flowgraph', flow):
1496
1509
  all_indices_failed = True
@@ -1578,13 +1591,15 @@ def _check_node_dependencies(chip, node, deps, deps_was_successful):
1578
1591
  # Fail if any dependency failed for non-builtin task
1579
1592
  if tool != 'builtin':
1580
1593
  deps.clear()
1581
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1594
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1595
+ step=step, index=index)
1582
1596
  return
1583
1597
 
1584
1598
  # Fail if no dependency successfully finished for builtin task
1585
1599
  if had_deps and len(deps) == 0 \
1586
1600
  and tool == 'builtin' and not deps_was_successful.get(node):
1587
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1601
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1602
+ step=step, index=index)
1588
1603
 
1589
1604
 
1590
1605
  def _launch_nodes(chip, nodes_to_run, processes, local_processes):
@@ -1629,6 +1644,8 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
1629
1644
  if _get_callback('pre_run'):
1630
1645
  _get_callback('pre_run')(chip)
1631
1646
 
1647
+ start_times = {None: time.time()}
1648
+
1632
1649
  while len(nodes_to_run) > 0 or len(running_nodes) > 0:
1633
1650
  changed = _process_completed_nodes(chip, processes, running_nodes)
1634
1651
 
@@ -1652,7 +1669,9 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
1652
1669
  if _get_callback('pre_node'):
1653
1670
  _get_callback('pre_node')(chip, *node)
1654
1671
 
1655
- chip.set('record', 'status', NodeStatus.RUNNING, step=node[0], index=node[1])
1672
+ chip.schema.get("record", field='schema').set('status', NodeStatus.RUNNING,
1673
+ step=node[0], index=node[1])
1674
+ start_times[node] = time.time()
1656
1675
  changed = True
1657
1676
 
1658
1677
  processes[node]["proc"].start()
@@ -1669,7 +1688,7 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
1669
1688
 
1670
1689
  if chip._dash and changed:
1671
1690
  # Update dashboard if the manifest changed
1672
- chip._dash.update_manifest()
1691
+ chip._dash.update_manifest(payload={"starttimes": start_times})
1673
1692
 
1674
1693
  if len(running_nodes) == 1:
1675
1694
  # if there is only one node running, just join the thread
@@ -1691,7 +1710,7 @@ def _process_completed_nodes(chip, processes, running_nodes):
1691
1710
  f'{chip.design}.pkg.json')
1692
1711
  chip.logger.debug(f'{step}{index} is complete merging: {manifest}')
1693
1712
  if os.path.exists(manifest):
1694
- chip.schema.read_journal(manifest)
1713
+ JournalingSchema(chip.schema).read_journal(manifest)
1695
1714
 
1696
1715
  if processes[node]["parent_pipe"] and processes[node]["parent_pipe"].poll(1):
1697
1716
  try:
@@ -1709,7 +1728,7 @@ def _process_completed_nodes(chip, processes, running_nodes):
1709
1728
  if not status or status == NodeStatus.PENDING:
1710
1729
  status = NodeStatus.ERROR
1711
1730
 
1712
- chip.set('record', 'status', status, step=step, index=index)
1731
+ chip.schema.get("record", field='schema').set('status', status, step=step, index=index)
1713
1732
 
1714
1733
  changed = True
1715
1734
 
@@ -1720,156 +1739,27 @@ def _process_completed_nodes(chip, processes, running_nodes):
1720
1739
 
1721
1740
 
1722
1741
  def _check_nodes_status(chip, flow):
1723
- def success(node):
1724
- return chip.get('record', 'status', step=node[0], index=node[1]) in \
1725
- (NodeStatus.SUCCESS, NodeStatus.SKIPPED)
1726
-
1727
- unreachable_steps = _unreachable_steps_to_execute(chip, flow, cond=success)
1728
- if unreachable_steps:
1742
+ flowgraph = chip.schema.get("flowgraph", flow, field="schema")
1743
+ runtime = RuntimeFlowgraph(
1744
+ flowgraph,
1745
+ from_steps=chip.get('option', 'from'),
1746
+ to_steps=chip.get('option', 'to'),
1747
+ prune_nodes=chip.get('option', 'prune'))
1748
+ runtime_no_prune = RuntimeFlowgraph(
1749
+ flowgraph,
1750
+ from_steps=chip.get('option', 'from'),
1751
+ to_steps=chip.get('option', 'to'))
1752
+
1753
+ all_steps = [step for step, index in runtime_no_prune.get_exit_nodes()
1754
+ if (step, index) not in chip.get('option', 'prune')]
1755
+ complete_steps = [step for step, _ in runtime.get_completed_nodes(
1756
+ record=chip.schema.get("record", field='schema'))]
1757
+
1758
+ unreached = set(all_steps).difference(complete_steps)
1759
+
1760
+ if unreached:
1729
1761
  raise SiliconCompilerError(
1730
- f'These final steps could not be reached: {list(unreachable_steps)}', chip=chip)
1731
-
1732
-
1733
- #######################################
1734
- def __record_version(chip, step, index):
1735
- chip.set('record', 'scversion', _metadata.version, step=step, index=index)
1736
- chip.set('record', 'pythonversion', platform.python_version(), step=step, index=index)
1737
-
1738
-
1739
- #######################################
1740
- def __record_packages(chip):
1741
- try:
1742
- from pip._internal.operations.freeze import freeze
1743
- except: # noqa E722
1744
- freeze = None
1745
-
1746
- if freeze:
1747
- # clear record
1748
- chip.set('record', 'pythonpackage', [])
1749
-
1750
- for pkg in freeze():
1751
- chip.add('record', 'pythonpackage', pkg)
1752
-
1753
-
1754
- #######################################
1755
- def __record_time(chip, step, index, record_time, timetype):
1756
- formatted_time = datetime.fromtimestamp(record_time).strftime('%Y-%m-%d %H:%M:%S')
1757
-
1758
- if timetype == 'start':
1759
- key = 'starttime'
1760
- elif timetype == 'end':
1761
- key = 'endtime'
1762
- else:
1763
- raise ValueError(f'{timetype} is not a valid time record')
1764
-
1765
- chip.set('record', key, formatted_time, step=step, index=index)
1766
-
1767
-
1768
- def get_record_time(chip, step, index, timetype):
1769
- return datetime.strptime(
1770
- chip.get('record', timetype, step=step, index=index),
1771
- '%Y-%m-%d %H:%M:%S').timestamp()
1772
-
1773
-
1774
- #######################################
1775
- def _get_cloud_region():
1776
- # TODO: add logic to figure out if we're running on a remote cluster and
1777
- # extract the region in a provider-specific way.
1778
- return 'local'
1779
-
1780
-
1781
- #######################################
1782
- def __record_usermachine(chip, step, index):
1783
- machine_info = _get_machine_info()
1784
- chip.set('record', 'platform', machine_info['system'], step=step, index=index)
1785
-
1786
- if machine_info['distro']:
1787
- chip.set('record', 'distro', machine_info['distro'], step=step, index=index)
1788
-
1789
- chip.set('record', 'osversion', machine_info['osversion'], step=step, index=index)
1790
-
1791
- if machine_info['kernelversion']:
1792
- chip.set('record', 'kernelversion', machine_info['kernelversion'], step=step, index=index)
1793
-
1794
- chip.set('record', 'arch', machine_info['arch'], step=step, index=index)
1795
-
1796
- chip.set('record', 'userid', getpass.getuser(), step=step, index=index)
1797
-
1798
- chip.set('record', 'machine', platform.node(), step=step, index=index)
1799
-
1800
- chip.set('record', 'region', _get_cloud_region(), step=step, index=index)
1801
-
1802
- try:
1803
- for interface, addrs in psutil.net_if_addrs().items():
1804
- if interface == 'lo':
1805
- # don't consider loopback device
1806
- continue
1807
-
1808
- if not addrs:
1809
- # skip missing addrs
1810
- continue
1811
-
1812
- use_addr = False
1813
- for addr in addrs:
1814
- if addr.family == socket.AF_INET:
1815
- if not addr.address.startswith('127.'):
1816
- use_addr = True
1817
- break
1818
-
1819
- if use_addr:
1820
- ipaddr = None
1821
- macaddr = None
1822
- for addr in addrs:
1823
- if not ipaddr and addr.family == socket.AF_INET:
1824
- ipaddr = addr.address
1825
- if not ipaddr and addr.family == socket.AF_INET6:
1826
- ipaddr = addr.address
1827
- if not macaddr and addr.family == psutil.AF_LINK:
1828
- macaddr = addr.address
1829
-
1830
- chip.set('record', 'ipaddr', ipaddr, step=step, index=index)
1831
- chip.set('record', 'macaddr', macaddr, step=step, index=index)
1832
- break
1833
- except: # noqa E722
1834
- chip.logger.warning('Could not find default network interface info')
1835
-
1836
-
1837
- #######################################
1838
- def _get_machine_info():
1839
- system = platform.system()
1840
- if system == 'Darwin':
1841
- lower_sys_name = 'macos'
1842
- else:
1843
- lower_sys_name = system.lower()
1844
-
1845
- if system == 'Linux':
1846
- distro_name = distro.id()
1847
- else:
1848
- distro_name = None
1849
-
1850
- if system == 'Darwin':
1851
- osversion, _, _ = platform.mac_ver()
1852
- elif system == 'Linux':
1853
- osversion = distro.version()
1854
- else:
1855
- osversion = platform.release()
1856
-
1857
- if system == 'Linux':
1858
- kernelversion = platform.release()
1859
- elif system == 'Windows':
1860
- kernelversion = platform.version()
1861
- elif system == 'Darwin':
1862
- kernelversion = platform.release()
1863
- else:
1864
- kernelversion = None
1865
-
1866
- arch = platform.machine()
1867
-
1868
- return {'system': lower_sys_name,
1869
- 'distro': distro_name,
1870
- 'osversion': osversion,
1871
- 'kernelversion': kernelversion,
1872
- 'arch': arch}
1762
+ f'These final steps could not be reached: {",".join(sorted(unreached))}', chip=chip)
1873
1763
 
1874
1764
 
1875
1765
  def print_traceback(chip, exception):
@@ -2144,12 +2034,11 @@ def copy_old_run_dir(chip, org_jobname):
2144
2034
  return
2145
2035
 
2146
2036
  # Copy nodes forward
2147
- org_nodes = set(_nodes_to_execute(
2148
- chip,
2149
- flow,
2150
- _get_flowgraph_entry_nodes(chip, flow),
2151
- from_nodes,
2152
- chip.get('option', 'prune')))
2037
+ runtime = RuntimeFlowgraph(
2038
+ chip.schema.get("flowgraph", flow, field="schema"),
2039
+ to_steps=chip.get('option', 'from'),
2040
+ prune_nodes=chip.get('option', 'prune'))
2041
+ org_nodes = set(runtime.get_nodes())
2153
2042
 
2154
2043
  copy_nodes = org_nodes.difference(from_nodes)
2155
2044
 
@@ -2195,8 +2084,7 @@ def copy_old_run_dir(chip, org_jobname):
2195
2084
  # delete file as it might be a hard link
2196
2085
  os.remove(manifest)
2197
2086
  schema.set('option', 'jobname', chip.get('option', 'jobname'))
2198
- with open(manifest, 'w') as f:
2199
- schema.write_json(f)
2087
+ schema.write_manifest(manifest)
2200
2088
 
2201
2089
 
2202
2090
  def clean_node_dir(chip, step, index):
@@ -2226,7 +2114,8 @@ def clean_build_dir(chip):
2226
2114
  for step, index in nodes_to_execute(chip):
2227
2115
  clean_node_dir(chip, step, index)
2228
2116
 
2229
- all_nodes = set(_get_flowgraph_nodes(chip, flow=chip.get('option', 'flow')))
2117
+ all_nodes = set(chip.schema.get("flowgraph", chip.get('option', 'flow'),
2118
+ field="schema").get_nodes())
2230
2119
  old_nodes = __collect_nodes_in_workdir(chip)
2231
2120
  node_mismatch = old_nodes.difference(all_nodes)
2232
2121
  if node_mismatch:
@@ -2289,7 +2178,8 @@ def _check_manifest_dynamic(chip, step, index):
2289
2178
  paramtype = chip.get(*keypath, field='type')
2290
2179
  is_perstep = not chip.get(*keypath, field='pernode').is_never()
2291
2180
  if ('file' in paramtype) or ('dir' in paramtype):
2292
- for val, check_step, check_index in chip.schema._getvals(*keypath):
2181
+ for val, check_step, check_index in chip.schema.get(*keypath,
2182
+ field=None).getvalues():
2293
2183
  if is_perstep:
2294
2184
  if check_step is None:
2295
2185
  check_step = Schema.GLOBAL_KEY
@@ -2313,35 +2203,12 @@ def _check_manifest_dynamic(chip, step, index):
2313
2203
 
2314
2204
 
2315
2205
  #######################################
2316
- def _clear_metric(chip, step, index, metric, preserve=None):
2206
+ def _clear_metric(chip, step, index, metric):
2317
2207
  '''
2318
2208
  Helper function to clear metrics records
2319
2209
  '''
2320
2210
 
2321
- # This function is often called in a loop; don't clear
2322
- # metrics which the caller wants to preserve.
2323
- if preserve and metric in preserve:
2324
- return
2325
-
2326
2211
  flow = chip.get('option', 'flow')
2327
2212
  tool, task = get_tool_task(chip, step, index, flow=flow)
2328
2213
 
2329
- chip.unset('metric', metric, step=step, index=index)
2330
2214
  chip.unset('tool', tool, 'task', task, 'report', metric, step=step, index=index)
2331
-
2332
-
2333
- #######################################
2334
- def _clear_record(chip, step, index, record, preserve=None):
2335
- '''
2336
- Helper function to clear record parameters
2337
- '''
2338
-
2339
- # This function is often called in a loop; don't clear
2340
- # records which the caller wants to preserve.
2341
- if preserve and record in preserve:
2342
- return
2343
-
2344
- if chip.get('record', record, field='pernode').is_never():
2345
- chip.unset('record', record)
2346
- else:
2347
- chip.unset('record', record, step=step, index=index)