siliconcompiler 0.33.0__py3-none-any.whl → 0.33.2__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 (177) hide show
  1. siliconcompiler/_common.py +5 -0
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc_install.py +7 -0
  4. siliconcompiler/apps/sc_remote.py +7 -2
  5. siliconcompiler/apps/utils/replay.py +5 -5
  6. siliconcompiler/core.py +38 -12
  7. siliconcompiler/data/templates/replay/replay.sh.j2 +18 -1
  8. siliconcompiler/metric.py +78 -0
  9. siliconcompiler/package/git.py +1 -1
  10. siliconcompiler/record.py +63 -7
  11. siliconcompiler/remote/client.py +57 -14
  12. siliconcompiler/remote/server.py +110 -60
  13. siliconcompiler/report/dashboard/cli/__init__.py +2 -0
  14. siliconcompiler/report/dashboard/cli/board.py +34 -31
  15. siliconcompiler/report/report.py +10 -5
  16. siliconcompiler/report/utils.py +12 -6
  17. siliconcompiler/scheduler/__init__.py +146 -976
  18. siliconcompiler/scheduler/run_node.py +12 -5
  19. siliconcompiler/scheduler/send_messages.py +9 -3
  20. siliconcompiler/scheduler/slurm.py +10 -43
  21. siliconcompiler/scheduler/taskscheduler.py +320 -0
  22. siliconcompiler/schema/baseschema.py +25 -4
  23. siliconcompiler/schema/journalingschema.py +4 -0
  24. siliconcompiler/schema/schema_cfg.py +3 -3
  25. siliconcompiler/tool.py +201 -32
  26. siliconcompiler/tools/_common/__init__.py +14 -11
  27. siliconcompiler/tools/_common/asic.py +5 -5
  28. siliconcompiler/tools/bluespec/convert.py +2 -1
  29. siliconcompiler/tools/builtin/_common.py +9 -2
  30. siliconcompiler/tools/builtin/concatenate.py +6 -2
  31. siliconcompiler/tools/builtin/minimum.py +7 -2
  32. siliconcompiler/tools/builtin/mux.py +7 -2
  33. siliconcompiler/tools/builtin/nop.py +7 -2
  34. siliconcompiler/tools/builtin/verify.py +7 -3
  35. siliconcompiler/tools/chisel/convert.py +10 -10
  36. siliconcompiler/tools/klayout/drc.py +2 -2
  37. siliconcompiler/tools/klayout/klayout_show.py +6 -6
  38. siliconcompiler/tools/klayout/klayout_utils.py +12 -12
  39. siliconcompiler/tools/netgen/count_lvs.py +2 -2
  40. siliconcompiler/tools/netgen/lvs.py +1 -1
  41. siliconcompiler/tools/openroad/_apr.py +2 -2
  42. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -7
  43. siliconcompiler/tools/openroad/scripts/common/procs.tcl +18 -0
  44. siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -7
  45. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +10 -0
  46. siliconcompiler/tools/opensta/timing.py +11 -0
  47. siliconcompiler/tools/slang/__init__.py +6 -5
  48. siliconcompiler/tools/slang/elaborate.py +6 -6
  49. siliconcompiler/tools/slang/lint.py +1 -3
  50. siliconcompiler/tools/vpr/_xml_constraint.py +8 -8
  51. siliconcompiler/tools/yosys/prepareLib.py +2 -2
  52. siliconcompiler/tools/yosys/sc_synth_asic.tcl +43 -5
  53. siliconcompiler/tools/yosys/screenshot.py +1 -1
  54. siliconcompiler/tools/yosys/syn_asic.py +5 -5
  55. siliconcompiler/toolscripts/_tools.json +17 -10
  56. siliconcompiler/toolscripts/rhel8/install-chisel.sh +9 -2
  57. siliconcompiler/toolscripts/rhel8/install-icarus.sh +10 -3
  58. siliconcompiler/toolscripts/rhel8/install-klayout.sh +8 -1
  59. siliconcompiler/toolscripts/rhel8/install-magic.sh +9 -2
  60. siliconcompiler/toolscripts/rhel8/install-montage.sh +1 -1
  61. siliconcompiler/toolscripts/rhel8/install-netgen.sh +9 -2
  62. siliconcompiler/toolscripts/rhel8/install-slang.sh +11 -4
  63. siliconcompiler/toolscripts/rhel8/install-surelog.sh +9 -2
  64. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +11 -4
  65. siliconcompiler/toolscripts/rhel8/install-verible.sh +11 -3
  66. siliconcompiler/toolscripts/rhel8/install-verilator.sh +10 -3
  67. siliconcompiler/toolscripts/rhel8/install-xyce.sh +15 -10
  68. siliconcompiler/toolscripts/rhel9/install-chisel.sh +9 -2
  69. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +9 -2
  70. siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +10 -3
  71. siliconcompiler/toolscripts/rhel9/install-icarus.sh +10 -3
  72. siliconcompiler/toolscripts/rhel9/install-klayout.sh +8 -1
  73. siliconcompiler/toolscripts/rhel9/install-magic.sh +9 -2
  74. siliconcompiler/toolscripts/rhel9/install-montage.sh +1 -1
  75. siliconcompiler/toolscripts/rhel9/install-netgen.sh +9 -2
  76. siliconcompiler/toolscripts/rhel9/install-openroad.sh +16 -3
  77. siliconcompiler/toolscripts/rhel9/install-opensta.sh +17 -5
  78. siliconcompiler/toolscripts/rhel9/install-slang.sh +11 -4
  79. siliconcompiler/toolscripts/rhel9/install-surelog.sh +9 -2
  80. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +11 -4
  81. siliconcompiler/toolscripts/rhel9/install-verible.sh +11 -3
  82. siliconcompiler/toolscripts/rhel9/install-verilator.sh +10 -3
  83. siliconcompiler/toolscripts/rhel9/install-vpr.sh +9 -2
  84. siliconcompiler/toolscripts/rhel9/install-xdm.sh +10 -2
  85. siliconcompiler/toolscripts/rhel9/install-xyce.sh +15 -10
  86. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +9 -2
  87. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +10 -3
  88. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +10 -2
  89. siliconcompiler/toolscripts/rhel9/install-yosys.sh +9 -2
  90. siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +10 -2
  91. siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +10 -3
  92. siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +9 -2
  93. siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +9 -2
  94. siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +9 -2
  95. siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +9 -2
  96. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +9 -2
  97. siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +8 -1
  98. siliconcompiler/toolscripts/ubuntu20/install-magic.sh +9 -2
  99. siliconcompiler/toolscripts/ubuntu20/install-montage.sh +1 -1
  100. siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +9 -2
  101. siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +9 -2
  102. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +16 -3
  103. siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +16 -5
  104. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +11 -4
  105. siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +9 -2
  106. siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +10 -2
  107. siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +11 -4
  108. siliconcompiler/toolscripts/ubuntu20/install-verible.sh +11 -3
  109. siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +9 -2
  110. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +10 -2
  111. siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +13 -8
  112. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +9 -2
  113. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +9 -2
  114. siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +10 -2
  115. siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +10 -3
  116. siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +9 -2
  117. siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +9 -2
  118. siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +9 -2
  119. siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +9 -2
  120. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +9 -2
  121. siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +12 -1
  122. siliconcompiler/toolscripts/ubuntu22/install-magic.sh +9 -2
  123. siliconcompiler/toolscripts/ubuntu22/install-montage.sh +1 -1
  124. siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +9 -2
  125. siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +9 -2
  126. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +16 -3
  127. siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +17 -5
  128. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +11 -4
  129. siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +9 -2
  130. siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +10 -2
  131. siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +11 -4
  132. siliconcompiler/toolscripts/ubuntu22/install-verible.sh +11 -3
  133. siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +9 -2
  134. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +9 -2
  135. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +10 -2
  136. siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +13 -8
  137. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +9 -2
  138. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +10 -3
  139. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +10 -2
  140. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +9 -2
  141. siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +12 -4
  142. siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +10 -3
  143. siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +9 -2
  144. siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +9 -2
  145. siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +9 -2
  146. siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +9 -2
  147. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +9 -2
  148. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +12 -1
  149. siliconcompiler/toolscripts/ubuntu24/install-magic.sh +9 -2
  150. siliconcompiler/toolscripts/ubuntu24/install-montage.sh +1 -1
  151. siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +9 -2
  152. siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +9 -2
  153. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +16 -3
  154. siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +17 -5
  155. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +11 -4
  156. siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +9 -2
  157. siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +10 -2
  158. siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +11 -4
  159. siliconcompiler/toolscripts/ubuntu24/install-verible.sh +11 -3
  160. siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +9 -2
  161. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +9 -2
  162. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +10 -2
  163. siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +13 -8
  164. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +9 -2
  165. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +10 -3
  166. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +10 -2
  167. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +9 -2
  168. siliconcompiler/utils/__init__.py +11 -0
  169. siliconcompiler/utils/flowgraph.py +6 -101
  170. siliconcompiler/utils/issue.py +15 -23
  171. siliconcompiler/utils/logging.py +2 -2
  172. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/METADATA +6 -5
  173. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/RECORD +177 -176
  174. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/WHEEL +1 -1
  175. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/entry_points.txt +0 -0
  176. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/licenses/LICENSE +0 -0
  177. {siliconcompiler-0.33.0.dist-info → siliconcompiler-0.33.2.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,7 @@ class NodeStatus():
14
14
  SKIPPED = 'skipped'
15
15
  TIMEOUT = 'timeout'
16
16
 
17
+ @staticmethod
17
18
  def is_done(status):
18
19
  return status in (
19
20
  NodeStatus.SUCCESS,
@@ -22,23 +23,27 @@ class NodeStatus():
22
23
  NodeStatus.TIMEOUT
23
24
  )
24
25
 
26
+ @staticmethod
25
27
  def is_running(status):
26
28
  return status in (
27
29
  NodeStatus.QUEUED,
28
30
  NodeStatus.RUNNING
29
31
  )
30
32
 
33
+ @staticmethod
31
34
  def is_waiting(status):
32
35
  return status in (
33
36
  NodeStatus.PENDING,
34
37
  )
35
38
 
39
+ @staticmethod
36
40
  def is_success(status):
37
41
  return status in (
38
42
  NodeStatus.SUCCESS,
39
43
  NodeStatus.SKIPPED
40
44
  )
41
45
 
46
+ @staticmethod
42
47
  def is_error(status):
43
48
  return status in (
44
49
  NodeStatus.ERROR,
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.33.0'
2
+ version = '0.33.2'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -42,6 +42,13 @@ def install_tool(tool, script, build_dir, prefix):
42
42
  # setup environment
43
43
  env = os.environ.copy()
44
44
  env["PREFIX"] = prefix
45
+ env["USE_SUDO_INSTALL"] = "no"
46
+ try:
47
+ os.makedirs(prefix, exist_ok=True)
48
+ except PermissionError:
49
+ env["USE_SUDO_INSTALL"] = "yes"
50
+ if not os.access(prefix, os.W_OK):
51
+ env["USE_SUDO_INSTALL"] = "yes"
45
52
 
46
53
  # run
47
54
  ret = subprocess.call(script, env=env, cwd=build_dir)
@@ -6,7 +6,7 @@ from siliconcompiler import Chip
6
6
  from siliconcompiler import SiliconCompilerError
7
7
  from siliconcompiler.remote.client import Client, ConfigureClient
8
8
  from siliconcompiler.scheduler import _finalize_run
9
- from siliconcompiler.utils.flowgraph import nodes_to_execute
9
+ from siliconcompiler.flowgraph import RuntimeFlowgraph
10
10
 
11
11
 
12
12
  def main():
@@ -170,7 +170,12 @@ To delete a job, use:
170
170
  return 1
171
171
 
172
172
  # Wrap up run
173
- for step, index in nodes_to_execute(chip):
173
+ runtime = RuntimeFlowgraph(
174
+ chip.schema.get("flowgraph", flow, field='schema'),
175
+ from_steps=chip.get('option', 'from'),
176
+ to_steps=chip.get('option', 'to'),
177
+ prune_nodes=chip.get('option', 'prune'))
178
+ for step, index in runtime.get_nodes():
174
179
  manifest = os.path.join(chip.getworkdir(step=step, index=index),
175
180
  'outputs',
176
181
  f'{chip.design}.pkg.json')
@@ -18,6 +18,7 @@ import siliconcompiler
18
18
  from siliconcompiler.apps._common import UNSET_DESIGN
19
19
  from siliconcompiler import SiliconCompilerError
20
20
  from siliconcompiler import utils
21
+ from siliconcompiler.record import RecordTime
21
22
 
22
23
 
23
24
  def make_bytes(data):
@@ -127,11 +128,10 @@ def main():
127
128
  path = os.path.abspath(args['file'])
128
129
  os.makedirs(os.path.dirname(path), exist_ok=True)
129
130
 
130
- starttimes = set()
131
- for starttime, step, index in chip.schema.get('history', jobname, 'record', 'starttime',
132
- field=None).getvalues():
133
- starttimes.add(datetime.strptime(starttime, '%Y-%m-%d %H:%M:%S'))
134
- starttime = min(starttimes).strftime('%Y-%m-%d %H:%M:%S')
131
+ record_schema = chip.schema.get('history', jobname, 'record', field="schema")
132
+ starttime = datetime.fromtimestamp(
133
+ record_schema.get_earliest_time(RecordTime.START)).strftime(
134
+ '%Y-%m-%d %H:%M:%S')
135
135
 
136
136
  with io.StringIO() as fd:
137
137
  fd.write(utils.get_file_template('replay/requirements.txt').render(
siliconcompiler/core.py CHANGED
@@ -37,10 +37,7 @@ from siliconcompiler.report.dashboard import DashboardType
37
37
  from siliconcompiler import package as sc_package
38
38
  import glob
39
39
  from siliconcompiler.scheduler import run as sc_runner
40
- from siliconcompiler.utils.flowgraph import nodes_to_execute, \
41
- _get_pruned_node_inputs, \
42
- _get_flowgraph_execution_order, _check_flowgraph_io, \
43
- _get_flowgraph_information
40
+ from siliconcompiler.utils.flowgraph import _check_flowgraph_io, _get_flowgraph_information
44
41
  from siliconcompiler.tools._common import get_tool_task
45
42
  from types import FunctionType, ModuleType
46
43
  from siliconcompiler.flowgraph import RuntimeFlowgraph
@@ -1622,11 +1619,26 @@ class Chip:
1622
1619
  error = True
1623
1620
  self.logger.error(f"flowgraph {flow} not defined.")
1624
1621
 
1625
- nodes = [node for node in nodes_to_execute(self)
1622
+ runtime = RuntimeFlowgraph(
1623
+ self.schema.get("flowgraph", flow, field='schema'),
1624
+ args=(self.get('arg', 'step'), self.get('arg', 'index')),
1625
+ from_steps=self.get('option', 'from'),
1626
+ to_steps=self.get('option', 'to'),
1627
+ prune_nodes=self.get('option', 'prune'))
1628
+
1629
+ nodes = [node for node in runtime.get_nodes()
1626
1630
  if self.get('record', 'status', step=node[0], index=node[1])
1627
1631
  != NodeStatus.SKIPPED]
1632
+ flow_schema = self.schema.get("flowgraph", flow, field="schema")
1633
+ runtime_io = RuntimeFlowgraph(
1634
+ flow_schema,
1635
+ args=(self.get('arg', 'step'), self.get('arg', 'index')),
1636
+ from_steps=set([step for step, _ in flow_schema.get_entry_nodes()]),
1637
+ prune_nodes=self.get('option', 'prune'))
1638
+
1628
1639
  for (step, index) in nodes:
1629
- for in_step, in_index in _get_pruned_node_inputs(self, flow, (step, index)):
1640
+ for in_step, in_index in runtime_io.get_node_inputs(
1641
+ step, index, record=self.schema.get("record", field="schema")):
1630
1642
  if (in_step, in_index) in nodes:
1631
1643
  # we're gonna run this step, OK
1632
1644
  continue
@@ -1717,7 +1729,11 @@ class Chip:
1717
1729
  error = True
1718
1730
  self.logger.error(f'No executable or run() function specified for {tool}/{task}')
1719
1731
 
1720
- if not _check_flowgraph_io(self, nodes=nodes):
1732
+ runtime_full = RuntimeFlowgraph(
1733
+ self.schema.get("flowgraph", flow, field='schema'),
1734
+ to_steps=self.get('option', 'to'),
1735
+ prune_nodes=self.get('option', 'prune'))
1736
+ if not error and not _check_flowgraph_io(self, nodes=runtime_full.get_nodes()):
1721
1737
  error = True
1722
1738
 
1723
1739
  return not error
@@ -2748,7 +2764,13 @@ class Chip:
2748
2764
  flow = self.get('option', 'flow')
2749
2765
  flowgraph_nodes = [(step, index) for index in self.getkeys("flowgraph", flow, step)]
2750
2766
  else:
2751
- flowgraph_nodes = nodes_to_execute(self)
2767
+ flow = self.get('option', 'flow')
2768
+ runtime = RuntimeFlowgraph(
2769
+ self.schema.get("flowgraph", flow, field='schema'),
2770
+ from_steps=self.get('option', 'from'),
2771
+ to_steps=self.get('option', 'to'),
2772
+ prune_nodes=self.get('option', 'prune'))
2773
+ flowgraph_nodes = runtime.get_nodes()
2752
2774
 
2753
2775
  if not archive_name:
2754
2776
  if step and index:
@@ -3231,14 +3253,18 @@ class Chip:
3231
3253
  search_nodes.append((sc_step, sc_index))
3232
3254
  elif sc_step:
3233
3255
  if flow is not None:
3234
- for check_step, check_index in nodes_to_execute(self, flow):
3256
+ runtime = RuntimeFlowgraph(
3257
+ self.schema.get("flowgraph", flow, field='schema'),
3258
+ from_steps=self.get('option', 'from'),
3259
+ to_steps=self.get('option', 'to'),
3260
+ prune_nodes=self.get('option', 'prune'))
3261
+ for check_step, check_index in runtime.get_nodes():
3235
3262
  if sc_step == check_step:
3236
3263
  search_nodes.append((check_step, check_index))
3237
3264
  else:
3238
3265
  if flow is not None:
3239
- for nodes in _get_flowgraph_execution_order(self,
3240
- flow,
3241
- reverse=True):
3266
+ for nodes in self.schema.get(
3267
+ "flowgraph", flow, field="schema").get_execution_order(reverse=True):
3242
3268
  search_nodes.extend(nodes)
3243
3269
 
3244
3270
  for ext in self._showtools.keys():
@@ -9,6 +9,7 @@ CD_WORK="{{ work_dir }}"
9
9
  PRINT=""
10
10
  CMDPREFIX=""
11
11
  SKIPEXPORT=0
12
+ DONODE={{ node_only }}
12
13
  while [[ $# -gt 0 ]]; do
13
14
  case $1 in
14
15
  --which)
@@ -40,6 +41,11 @@ while [[ $# -gt 0 ]]; do
40
41
  shift
41
42
  shift
42
43
  ;;
44
+ --node)
45
+ DONODE=1
46
+ shift
47
+ shift
48
+ ;;
43
49
  -h|--help)
44
50
  echo "Usage: $0"
45
51
  echo " Options:"
@@ -49,7 +55,8 @@ while [[ $# -gt 0 ]]; do
49
55
  echo " --command print the execution command"
50
56
  echo " --skipcd do not change directory into replay directory"
51
57
  echo " --skipexports do not export environmental variables"
52
- echo " --cmdprefix <cmd> prefix to add to the replay command, such as gdb"
58
+ echo " --cmdprefix <cmd> prefix to add to the replay command, such as dgb"
59
+ echo " --node execute entire node"
53
60
  echo " -h,--help print this help"
54
61
  exit 0
55
62
  ;;
@@ -87,6 +94,16 @@ case $PRINT in
87
94
  ;;
88
95
  esac
89
96
 
97
+ if [ $DONODE == 1 ]; then
98
+ python3 -m siliconcompiler.scheduler.run_node \
99
+ -cfg "{{ cfg_file }}" \
100
+ -builddir "${PWD}/../../../../" \
101
+ -step "{{ step }}" \
102
+ -index "{{ index }}" \
103
+ -cwd "$PWD" \
104
+ -replay
105
+ {% if cmds|length > 0 %}else
90
106
  # Command execution
91
107
  $CMDPREFIX \{% for cmd in cmds %}
92
108
  {% if not loop.first %} {% endif %}{{ cmd }}{% if not loop.last %} \{% endif %}{% endfor %}
109
+ {% endif %}fi
siliconcompiler/metric.py CHANGED
@@ -3,6 +3,7 @@ from siliconcompiler.schema import EditableSchema, Parameter, PerNode, Scope
3
3
  from siliconcompiler.schema.utils import trim
4
4
 
5
5
  from siliconcompiler.utils.units import convert
6
+ from siliconcompiler.record import RecordTime
6
7
 
7
8
 
8
9
  class MetricSchema(BaseSchema):
@@ -43,6 +44,83 @@ class MetricSchema(BaseSchema):
43
44
 
44
45
  return self.set(metric, value, step=step, index=str(index))
45
46
 
47
+ def record_tasktime(self, step, index, record):
48
+ """
49
+ Record the task time for this node
50
+
51
+ Args:
52
+ step (str): step to record
53
+ index (str/int): index to record
54
+ record (:class:`RecordSchema`): record to lookup data in
55
+ """
56
+ start_time, end_time = [
57
+ record.get_recorded_time(step, index, RecordTime.START),
58
+ record.get_recorded_time(step, index, RecordTime.END)
59
+ ]
60
+
61
+ if start_time is None or end_time is None:
62
+ return False
63
+
64
+ return self.record(step, index, "tasktime", end_time-start_time, unit="s")
65
+
66
+ def record_totaltime(self, step, index, flow, record):
67
+ """
68
+ Record the total time for this node
69
+
70
+ Args:
71
+ step (str): step to record
72
+ index (str/int): index to record
73
+ flow (:class:`FlowgraphSchema`): flowgraph to lookup nodes in
74
+ record (:class:`RecordSchema`): record to lookup data in
75
+ """
76
+ all_nodes = flow.get_nodes()
77
+ node_times = [
78
+ (record.get_recorded_time(*node, RecordTime.START),
79
+ record.get_recorded_time(*node, RecordTime.END)) for node in all_nodes
80
+ ]
81
+
82
+ # Remove incomplete records
83
+ node_times = [times for times in node_times if times[0] is not None]
84
+
85
+ if len(node_times) == 0:
86
+ return False
87
+
88
+ node_end = record.get_recorded_time(step, index, RecordTime.END)
89
+ if node_end is None:
90
+ return False
91
+
92
+ node_times = sorted(node_times)
93
+ if len(node_times) > 1:
94
+ new_times = []
95
+ for n in range(len(node_times)):
96
+ if not new_times:
97
+ new_times.append(node_times[n])
98
+ continue
99
+ prev_start_time, prev_end_time = new_times[-1]
100
+ start_time, end_time = node_times[n]
101
+
102
+ new_start = min(prev_start_time, start_time)
103
+
104
+ if prev_end_time is None:
105
+ new_times[-1] = (new_start, end_time)
106
+ elif prev_end_time >= start_time:
107
+ if end_time is not None:
108
+ new_end = max(prev_end_time, end_time)
109
+ else:
110
+ new_end = prev_end_time
111
+ new_times[-1] = (new_start, new_end)
112
+ else:
113
+ new_times.append(node_times[n])
114
+ node_times = new_times
115
+
116
+ total_time = 0
117
+ for start_time, end_time in node_times:
118
+ if start_time > node_end:
119
+ continue
120
+ total_time += min(end_time, node_end) - start_time
121
+
122
+ return self.record(step, index, "totaltime", total_time, unit="s")
123
+
46
124
 
47
125
  ###########################################################################
48
126
  # Metrics to Track
@@ -81,4 +81,4 @@ def clone_from_git(chip, package, path, ref, url, data_path):
81
81
  chip.logger.info(f'Checking out {ref}')
82
82
  repo.git.checkout(ref)
83
83
  for submodule in repo.submodules:
84
- submodule.update(init=True)
84
+ submodule.update(recursive=True, init=True, force=True)
siliconcompiler/record.py CHANGED
@@ -30,13 +30,25 @@ class RecordTool(Enum):
30
30
 
31
31
 
32
32
  class RecordSchema(BaseSchema):
33
- __TIMEFORMAT = "%Y-%m-%d %H:%M:%S"
33
+ __TIMEFORMAT = "%Y-%m-%d %H:%M:%S.%f"
34
34
 
35
35
  def __init__(self):
36
36
  super().__init__()
37
37
 
38
38
  schema_record(self)
39
39
 
40
+ def _from_dict(self, manifest, keypath, version=None):
41
+ ret = super()._from_dict(manifest, keypath, version)
42
+
43
+ # Correct for change specification
44
+ if version and version < (0, 50, 4):
45
+ for timekey in RecordTime:
46
+ start_param = self.get(timekey.value, field=None)
47
+ for value, step, index in start_param.getvalues():
48
+ start_param.set(f"{value}.000000", step=step, index=index)
49
+
50
+ return ret
51
+
40
52
  def clear(self, step, index, keep=None):
41
53
  '''
42
54
  Clear all saved metrics for a given step and index
@@ -259,7 +271,7 @@ class RecordSchema(BaseSchema):
259
271
 
260
272
  def get_recorded_time(self, step, index, type):
261
273
  '''
262
- Returns the time recorded for a given record.
274
+ Returns the time recorded for a given record, or None if nothing is recorded.
263
275
 
264
276
  Args:
265
277
  step (str): Step name to associate.
@@ -267,10 +279,52 @@ class RecordSchema(BaseSchema):
267
279
  type (:class:`RecordTime`): type of time to record
268
280
  '''
269
281
  type = RecordTime(type)
282
+ record_time = self.get(type.value, step=step, index=index)
283
+ if record_time is None:
284
+ return None
285
+
270
286
  return datetime.strptime(
271
- self.get(type.value, step=step, index=index)+"+0000",
287
+ record_time+"+0000",
272
288
  RecordSchema.__TIMEFORMAT+"%z").timestamp()
273
289
 
290
+ def get_earliest_time(self, type):
291
+ '''
292
+ Returns the earliest recorded time.
293
+
294
+ Args:
295
+ type (:class:`RecordTime`): type of time to record
296
+ '''
297
+ type = RecordTime(type)
298
+ record_param = self.get(type.value, field=None)
299
+
300
+ times = set()
301
+ for _, step, index in record_param.getvalues():
302
+ times.add(self.get_recorded_time(step, index, type))
303
+
304
+ if not times:
305
+ return None
306
+
307
+ return min(times)
308
+
309
+ def get_latest_time(self, type):
310
+ '''
311
+ Returns the last recorded time.
312
+
313
+ Args:
314
+ type (:class:`RecordTime`): type of time to record
315
+ '''
316
+ type = RecordTime(type)
317
+ record_param = self.get(type.value, field=None)
318
+
319
+ times = set()
320
+ for _, step, index in record_param.getvalues():
321
+ times.add(self.get_recorded_time(step, index, type))
322
+
323
+ if not times:
324
+ return None
325
+
326
+ return max(times)
327
+
274
328
  def record_tool(self, step, index, info, type):
275
329
  '''
276
330
  Record information about the tool used during this record.
@@ -316,11 +370,13 @@ def schema_record(schema):
316
370
  'x86_64',
317
371
  '(x86_64, rv64imafdc)'],
318
372
  'starttime': ['start time',
319
- '\"2021-09-06 12:20:20\"',
320
- 'Time is reported in the ISO 8601 format YYYY-MM-DD HR:MIN:SEC'],
373
+ '\"2021-09-06 12:20:20.000000\"',
374
+ 'Time is recorded with the format YYYY-MM-DD HR:MIN:SEC.MICROSEC for '
375
+ 'UTC'],
321
376
  'endtime': ['end time',
322
- '\"2021-09-06 12:20:20\"',
323
- 'Time is reported in the ISO 8601 format YYYY-MM-DD HR:MIN:SEC'],
377
+ '\"2021-09-06 12:20:20.000000\"',
378
+ 'Time is recorded with the format YYYY-MM-DD HR:MIN:SEC.MICROSEC for '
379
+ 'UTC'],
324
380
  'region': ['cloud region',
325
381
  '\"US Gov Boston\"',
326
382
  """Recommended naming methodology:
@@ -10,12 +10,15 @@ import tarfile
10
10
  import tempfile
11
11
  import multiprocessing
12
12
 
13
- from siliconcompiler import utils, SiliconCompilerError, NodeStatus
13
+ import os.path
14
+
15
+ from siliconcompiler import utils, SiliconCompilerError
14
16
  from siliconcompiler import NodeStatus as SCNodeStatus
15
17
  from siliconcompiler._metadata import default_server
16
- from siliconcompiler.utils.flowgraph import nodes_to_execute
17
- from siliconcompiler.remote import JobStatus
18
+ from siliconcompiler.remote import JobStatus, NodeStatus
18
19
  from siliconcompiler.report.dashboard import DashboardType
20
+ from siliconcompiler.flowgraph import RuntimeFlowgraph
21
+ from siliconcompiler.schema import JournalingSchema
19
22
 
20
23
  # Step name to use while logging
21
24
  remote_step_name = 'remote'
@@ -309,19 +312,29 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
309
312
  try:
310
313
  # Decode response JSON, if possible.
311
314
  job_info = json.loads(info['message'])
312
- except json.JSONDecodeError as e:
313
- self.__logger.warning(f"Job is still running: {e}")
315
+ if "null" in job_info:
316
+ job_info[None] = job_info["null"]
317
+ del job_info["null"]
318
+ except json.JSONDecodeError:
319
+ self.__logger.warning(f"Job is still running: {info['message']}")
314
320
  return completed, starttimes, True
315
321
 
316
322
  nodes_to_log = {}
317
323
  for node, node_info in job_info.items():
318
324
  status = node_info['status']
319
- nodes_to_log.setdefault(status, []).append((node, node_info))
325
+
326
+ if status == NodeStatus.UPLOADED:
327
+ status = SCNodeStatus.PENDING
320
328
 
321
329
  if SCNodeStatus.is_done(status):
322
330
  # collect completed
323
331
  completed.append(node)
324
332
 
333
+ if not node:
334
+ continue
335
+
336
+ nodes_to_log.setdefault(status, []).append((node, node_info))
337
+
325
338
  if self.__node_information and node in self.__node_information:
326
339
  self.__chip.set('record', 'status', status,
327
340
  step=self.__node_information[node]["step"],
@@ -579,6 +592,22 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
579
592
  raise SiliconCompilerError('Job canceled by user keyboard interrupt')
580
593
 
581
594
  def __import_run_manifests(self, starttimes):
595
+ if not self.__setup_information_loaded:
596
+ if self.__setup_information_fetched:
597
+ manifest = os.path.join(self.__chip.getworkdir(), f'{self.__chip.design}.pkg.json')
598
+ if os.path.exists(manifest):
599
+ try:
600
+ JournalingSchema(self.__chip.schema).read_journal(manifest)
601
+ self.__setup_information_loaded = True
602
+ changed = True
603
+ except: # noqa E722
604
+ # Import may fail if file is still getting written
605
+ pass
606
+
607
+ if not self.__setup_information_loaded:
608
+ # Dont do anything until this has been loaded
609
+ return
610
+
582
611
  changed = False
583
612
  for _, node_info in self.__node_information.items():
584
613
  if node_info["imported"]:
@@ -590,7 +619,7 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
590
619
  f'{self.__chip.design}.pkg.json')
591
620
  if os.path.exists(manifest):
592
621
  try:
593
- self.__chip.schema.read_journal(manifest)
622
+ JournalingSchema(self.__chip.schema).read_journal(manifest)
594
623
  node_info["imported"] = True
595
624
  changed = True
596
625
  except: # noqa E722
@@ -598,7 +627,7 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
598
627
  pass
599
628
  elif self.__chip.get('record', 'status',
600
629
  step=node_info["step"], index=node_info["index"]) \
601
- == NodeStatus.SKIPPED:
630
+ == SCNodeStatus.SKIPPED:
602
631
  node_info["imported"] = True
603
632
  changed = True
604
633
 
@@ -617,8 +646,17 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
617
646
  check_info = self.__check()
618
647
  self.__check_interval = check_info['progress_interval']
619
648
 
649
+ self.__setup_information_fetched = False
650
+ self.__setup_information_loaded = False
651
+
620
652
  self.__node_information = {}
621
- for step, index in nodes_to_execute(self.__chip):
653
+ runtime = RuntimeFlowgraph(
654
+ self.__chip.schema.get("flowgraph", self.__chip.get('option', 'flow'), field='schema'),
655
+ from_steps=self.__chip.get('option', 'from'),
656
+ to_steps=self.__chip.get('option', 'to'),
657
+ prune_nodes=self.__chip.get('option', 'prune'))
658
+
659
+ for step, index in runtime.get_nodes():
622
660
  done = SCNodeStatus.is_done(self.__chip.get('record', 'status', step=step, index=index))
623
661
  node_info = {
624
662
  "step": step,
@@ -659,6 +697,11 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
659
697
  # Update dashboard if active
660
698
  self.__chip._dash.update_manifest({"starttimes": starttimes})
661
699
 
700
+ if None in completed:
701
+ completed.remove(None)
702
+ if not self.__setup_information_fetched:
703
+ self.__schedule_fetch_result(None)
704
+
662
705
  nodes_to_fetch = []
663
706
  for node in completed:
664
707
  if not self.__node_information[node]["fetched"]:
@@ -674,7 +717,6 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
674
717
  for node, node_info in self.__node_information.items():
675
718
  if not node_info["fetched"]:
676
719
  self.__schedule_fetch_result(node)
677
- self.__schedule_fetch_result(node)
678
720
 
679
721
  self._finalize_loop()
680
722
 
@@ -693,11 +735,12 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
693
735
  self.__import_run_manifests({})
694
736
 
695
737
  def __schedule_fetch_result(self, node):
696
- self.__node_information[node]["fetched"] = True
738
+ if node:
739
+ self.__node_information[node]["fetched"] = True
740
+ self.__logger.info(f' {node}')
741
+ else:
742
+ self.__setup_information_fetched = True
697
743
  self.__download_pool.apply_async(Client._fetch_result, (self, node))
698
- if node is None:
699
- node = 'final result'
700
- self.__logger.info(f' {node}')
701
744
 
702
745
  def _fetch_result(self, node):
703
746
  '''