siliconcompiler 0.32.2__py3-none-any.whl → 0.32.3__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 (172) hide show
  1. siliconcompiler/_metadata.py +3 -2
  2. siliconcompiler/core.py +52 -56
  3. siliconcompiler/issue.py +3 -1
  4. siliconcompiler/remote/client.py +55 -16
  5. siliconcompiler/report/__init__.py +3 -2
  6. siliconcompiler/report/dashboard/__init__.py +61 -170
  7. siliconcompiler/report/dashboard/cli/__init__.py +788 -0
  8. siliconcompiler/report/dashboard/web/__init__.py +196 -0
  9. siliconcompiler/report/dashboard/{components → web/components}/__init__.py +4 -4
  10. siliconcompiler/report/dashboard/{components → web/components}/graph.py +1 -1
  11. siliconcompiler/report/dashboard/{layouts → web/layouts}/__init__.py +3 -3
  12. siliconcompiler/report/dashboard/{layouts → web/layouts}/_common.py +1 -1
  13. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph.py +5 -5
  14. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph_node_tab.py +6 -6
  15. siliconcompiler/report/dashboard/{layouts → web/layouts}/vertical_flowgraph_sac_tabs.py +6 -6
  16. siliconcompiler/report/dashboard/{viewer.py → web/viewer.py} +4 -4
  17. siliconcompiler/scheduler/__init__.py +8 -6
  18. siliconcompiler/templates/replay/replay.sh.j2 +2 -2
  19. siliconcompiler/tools/_common/__init__.py +2 -0
  20. siliconcompiler/tools/openroad/_apr.py +4 -0
  21. siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -14
  22. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +1 -1
  23. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +1 -1
  24. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +1 -1
  25. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +1 -1
  26. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +1 -1
  27. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +1 -1
  28. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +2 -2
  29. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +1 -1
  30. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +1 -1
  31. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -1
  32. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +1 -1
  33. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +1 -1
  34. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +1 -1
  35. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +1 -1
  36. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -1
  37. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +2 -2
  38. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +1 -1
  39. siliconcompiler/tools/openroad/scripts/common/procs.tcl +1 -1
  40. siliconcompiler/tools/openroad/scripts/common/reports.tcl +2 -2
  41. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +1 -1
  42. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +1 -1
  43. siliconcompiler/tools/openroad/scripts/sc_show.tcl +1 -1
  44. siliconcompiler/tools/opensta/__init__.py +1 -1
  45. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +1 -1
  46. siliconcompiler/tools/opensta/scripts/sc_procs.tcl +16 -0
  47. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +1 -1
  48. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +35 -7
  49. siliconcompiler/tools/opensta/timing.py +6 -2
  50. siliconcompiler/tools/yosys/sc_synth_asic.tcl +36 -28
  51. siliconcompiler/tools/yosys/syn_asic.py +11 -2
  52. siliconcompiler/toolscripts/_tools.json +9 -4
  53. siliconcompiler/toolscripts/rhel8/install-chisel.sh +2 -0
  54. siliconcompiler/toolscripts/rhel8/install-icarus.sh +1 -0
  55. siliconcompiler/toolscripts/rhel8/install-klayout.sh +2 -0
  56. siliconcompiler/toolscripts/rhel8/install-magic.sh +1 -2
  57. siliconcompiler/toolscripts/rhel8/install-netgen.sh +1 -1
  58. siliconcompiler/toolscripts/rhel8/install-slang.sh +2 -0
  59. siliconcompiler/toolscripts/rhel8/install-surelog.sh +3 -1
  60. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +1 -0
  61. siliconcompiler/toolscripts/rhel8/install-verible.sh +2 -0
  62. siliconcompiler/toolscripts/rhel8/install-verilator.sh +1 -0
  63. siliconcompiler/toolscripts/rhel8/install-xyce.sh +2 -0
  64. siliconcompiler/toolscripts/rhel9/install-chisel.sh +2 -0
  65. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +1 -0
  66. siliconcompiler/toolscripts/rhel9/install-gtkwave.sh +1 -0
  67. siliconcompiler/toolscripts/rhel9/install-icarus.sh +1 -0
  68. siliconcompiler/toolscripts/rhel9/install-klayout.sh +2 -0
  69. siliconcompiler/toolscripts/rhel9/install-magic.sh +1 -2
  70. siliconcompiler/toolscripts/rhel9/install-netgen.sh +1 -1
  71. siliconcompiler/toolscripts/rhel9/install-openroad.sh +2 -0
  72. siliconcompiler/toolscripts/rhel9/install-opensta.sh +76 -0
  73. siliconcompiler/toolscripts/rhel9/install-slang.sh +3 -1
  74. siliconcompiler/toolscripts/rhel9/install-surelog.sh +2 -1
  75. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +1 -0
  76. siliconcompiler/toolscripts/rhel9/install-verible.sh +2 -0
  77. siliconcompiler/toolscripts/rhel9/install-verilator.sh +1 -0
  78. siliconcompiler/toolscripts/rhel9/install-vpr.sh +2 -0
  79. siliconcompiler/toolscripts/rhel9/install-xdm.sh +2 -0
  80. siliconcompiler/toolscripts/rhel9/install-xyce.sh +2 -0
  81. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +2 -0
  82. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +2 -0
  83. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +3 -1
  84. siliconcompiler/toolscripts/rhel9/install-yosys.sh +2 -0
  85. siliconcompiler/toolscripts/ubuntu20/install-bambu.sh +2 -0
  86. siliconcompiler/toolscripts/ubuntu20/install-bluespec.sh +2 -0
  87. siliconcompiler/toolscripts/ubuntu20/install-chisel.sh +2 -0
  88. siliconcompiler/toolscripts/ubuntu20/install-ghdl.sh +2 -0
  89. siliconcompiler/toolscripts/ubuntu20/install-gtkwave.sh +2 -0
  90. siliconcompiler/toolscripts/ubuntu20/install-icarus.sh +2 -0
  91. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +2 -0
  92. siliconcompiler/toolscripts/ubuntu20/install-klayout.sh +2 -0
  93. siliconcompiler/toolscripts/ubuntu20/install-magic.sh +2 -0
  94. siliconcompiler/toolscripts/ubuntu20/install-netgen.sh +2 -0
  95. siliconcompiler/toolscripts/ubuntu20/install-nextpnr.sh +1 -3
  96. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +2 -0
  97. siliconcompiler/toolscripts/ubuntu20/install-opensta.sh +72 -0
  98. siliconcompiler/toolscripts/ubuntu20/install-slang.sh +3 -1
  99. siliconcompiler/toolscripts/ubuntu20/install-slurm.sh +2 -0
  100. siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +3 -1
  101. siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +1 -1
  102. siliconcompiler/toolscripts/ubuntu20/install-verible.sh +2 -0
  103. siliconcompiler/toolscripts/ubuntu20/install-verilator.sh +2 -0
  104. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +2 -0
  105. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +2 -0
  106. siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +2 -0
  107. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +2 -0
  108. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +2 -0
  109. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +2 -0
  110. siliconcompiler/toolscripts/ubuntu22/install-bambu.sh +2 -0
  111. siliconcompiler/toolscripts/ubuntu22/install-bluespec.sh +2 -0
  112. siliconcompiler/toolscripts/ubuntu22/install-chisel.sh +2 -0
  113. siliconcompiler/toolscripts/ubuntu22/install-ghdl.sh +2 -0
  114. siliconcompiler/toolscripts/ubuntu22/install-gtkwave.sh +2 -0
  115. siliconcompiler/toolscripts/ubuntu22/install-icarus.sh +2 -0
  116. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +2 -0
  117. siliconcompiler/toolscripts/ubuntu22/install-klayout.sh +2 -0
  118. siliconcompiler/toolscripts/ubuntu22/install-magic.sh +2 -0
  119. siliconcompiler/toolscripts/ubuntu22/install-netgen.sh +2 -0
  120. siliconcompiler/toolscripts/ubuntu22/install-nextpnr.sh +1 -2
  121. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +2 -0
  122. siliconcompiler/toolscripts/ubuntu22/install-opensta.sh +72 -0
  123. siliconcompiler/toolscripts/ubuntu22/install-slang.sh +3 -1
  124. siliconcompiler/toolscripts/ubuntu22/install-slurm.sh +2 -0
  125. siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +3 -1
  126. siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +1 -1
  127. siliconcompiler/toolscripts/ubuntu22/install-verible.sh +2 -0
  128. siliconcompiler/toolscripts/ubuntu22/install-verilator.sh +2 -0
  129. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +2 -0
  130. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +2 -0
  131. siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +2 -0
  132. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +2 -0
  133. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +2 -0
  134. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +3 -1
  135. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +2 -0
  136. siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +2 -0
  137. siliconcompiler/toolscripts/ubuntu24/install-bluespec.sh +2 -0
  138. siliconcompiler/toolscripts/ubuntu24/install-chisel.sh +2 -0
  139. siliconcompiler/toolscripts/ubuntu24/install-ghdl.sh +2 -0
  140. siliconcompiler/toolscripts/ubuntu24/install-gtkwave.sh +2 -0
  141. siliconcompiler/toolscripts/ubuntu24/install-icarus.sh +2 -0
  142. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +2 -0
  143. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +2 -0
  144. siliconcompiler/toolscripts/ubuntu24/install-magic.sh +2 -0
  145. siliconcompiler/toolscripts/ubuntu24/install-netgen.sh +2 -0
  146. siliconcompiler/toolscripts/ubuntu24/install-nextpnr.sh +1 -3
  147. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +2 -0
  148. siliconcompiler/toolscripts/ubuntu24/install-opensta.sh +72 -0
  149. siliconcompiler/toolscripts/ubuntu24/install-slang.sh +3 -1
  150. siliconcompiler/toolscripts/ubuntu24/install-slurm.sh +2 -0
  151. siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +3 -1
  152. siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +1 -1
  153. siliconcompiler/toolscripts/ubuntu24/install-verible.sh +2 -0
  154. siliconcompiler/toolscripts/ubuntu24/install-verilator.sh +2 -0
  155. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +2 -0
  156. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +2 -0
  157. siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +2 -0
  158. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +2 -0
  159. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +2 -0
  160. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +3 -1
  161. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +2 -0
  162. siliconcompiler/utils/logging.py +87 -33
  163. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/METADATA +5 -4
  164. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/RECORD +172 -166
  165. /siliconcompiler/report/dashboard/{components → web/components}/flowgraph.py +0 -0
  166. /siliconcompiler/report/dashboard/{state.py → web/state.py} +0 -0
  167. /siliconcompiler/report/dashboard/{utils → web/utils}/__init__.py +0 -0
  168. /siliconcompiler/report/dashboard/{utils → web/utils}/file_utils.py +0 -0
  169. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/WHEEL +0 -0
  170. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/entry_points.txt +0 -0
  171. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/licenses/LICENSE +0 -0
  172. {siliconcompiler-0.32.2.dist-info → siliconcompiler-0.32.3.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.32.2'
2
+ version = '0.32.3'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -21,7 +21,8 @@ authors = [
21
21
  'Aulihan Teng',
22
22
  'Peter Grossmann',
23
23
  'Gabriel Aguirre',
24
- 'Martin Troiber'
24
+ 'Martin Troiber',
25
+ 'Ciprian Antoci'
25
26
  ]
26
27
 
27
28
  # CLI entry banner autogenerated using pyfiglet.
siliconcompiler/core.py CHANGED
@@ -17,16 +17,20 @@ import graphviz
17
17
  import codecs
18
18
  import copy
19
19
  from inspect import getfullargspec
20
- from siliconcompiler.remote import client
21
20
  from siliconcompiler.schema import Schema, SCHEMA_VERSION
22
21
  from siliconcompiler.schema import utils as schema_utils
23
22
  from siliconcompiler import utils
24
- from siliconcompiler.utils.logging import LoggerFormatter, ColorStreamFormatter
23
+ from siliconcompiler.utils.logging import SCColorLoggerFormatter, \
24
+ SCLoggerFormatter, SCInRunLoggerFormatter, \
25
+ SCDebugLoggerFormatter, SCDebugInRunLoggerFormatter, \
26
+ SCBlankLoggerFormatter
25
27
  from siliconcompiler import _metadata
26
28
  from siliconcompiler import NodeStatus, SiliconCompilerError
27
29
  from siliconcompiler.report import _show_summary_table
28
30
  from siliconcompiler.report import _generate_summary_image, _open_summary_image
29
- from siliconcompiler.report import Dashboard
31
+ from siliconcompiler.report.dashboard.web import WebDashboard
32
+ from siliconcompiler.report.dashboard.cli import CliDashboard
33
+ from siliconcompiler.report.dashboard import DashboardType
30
34
  from siliconcompiler import package as sc_package
31
35
  import glob
32
36
  from siliconcompiler.scheduler import run as sc_runner
@@ -238,62 +242,39 @@ class Chip:
238
242
  self.logger._console = stream_handler
239
243
  self.logger.addHandler(stream_handler)
240
244
 
241
- self.logger._support_color = ColorStreamFormatter.supports_color(stream_handler)
245
+ self.logger._support_color = SCColorLoggerFormatter.supports_color(stream_handler)
242
246
 
243
247
  self._init_logger_formats(loglevel=loglevel)
244
248
 
245
249
  def _init_logger_formats(self, loglevel=None):
246
250
  if not loglevel:
247
- self.schema.get('option', 'loglevel',
248
- step=self.logger._in_step, index=self.logger._in_index)
249
-
250
- level_format = '%(levelname)-7s'
251
- log_format = [level_format]
252
- if loglevel == 'debug':
253
- log_format.append('%(funcName)-10s')
254
- log_format.append('%(lineno)-4s')
255
-
256
- if self.logger._in_run:
257
- max_column_width = 20
258
- # Figure out how wide to make step and index fields
259
- max_step_len = 1
260
- max_index_len = 1
261
- nodes_to_run = _get_flowgraph_nodes(self, flow=self.get('option', 'flow'))
262
- if self.get('option', 'remote'):
263
- nodes_to_run.append((client.remote_step_name, '0'))
264
- for future_step, future_index in nodes_to_run:
265
- max_step_len = max(len(future_step), max_step_len)
266
- max_index_len = max(len(future_index), max_index_len)
267
- max_step_len = min(max_step_len, max_column_width)
268
- max_index_len = min(max_index_len, max_column_width)
269
-
270
- jobname = self.get('option', 'jobname')
271
-
272
- step = self.logger._in_step
273
- index = self.logger._in_index
274
-
275
- if step is None:
276
- step = '-' * max(max_step_len // 4, 1)
277
- if index is None:
278
- index = '-' * max(max_index_len // 4, 1)
279
-
280
- log_format.append(utils.truncate_text(jobname, max_column_width))
281
- log_format.append(f'{utils.truncate_text(step, max_step_len): <{max_step_len}}')
282
- log_format.append(f'{utils.truncate_text(index, max_step_len): >{max_index_len}}')
283
-
284
- log_formatprefix = "| "
285
- if loglevel == "quiet":
286
- log_format = []
287
- log_formatprefix = ""
288
-
289
- log_format.append('%(message)s')
290
- stream_logformat = log_formatprefix + ' | '.join(log_format[1:])
251
+ loglevel = self.schema.get('option', 'loglevel',
252
+ step=self.logger._in_step, index=self.logger._in_index)
253
+
254
+ if loglevel == 'quiet':
255
+ base_format = SCBlankLoggerFormatter()
256
+ elif self.logger._in_run:
257
+ if loglevel == 'debug':
258
+ base_format = SCDebugInRunLoggerFormatter(
259
+ self,
260
+ self.get('option', 'jobname'),
261
+ self.logger._in_step, self.logger._in_index)
262
+ else:
263
+ base_format = SCInRunLoggerFormatter(
264
+ self,
265
+ self.get('option', 'jobname'),
266
+ self.logger._in_step, self.logger._in_index)
267
+ else:
268
+ if loglevel == 'debug':
269
+ base_format = SCDebugLoggerFormatter()
270
+ else:
271
+ base_format = SCLoggerFormatter()
291
272
 
292
273
  for handler in self.logger.handlers.copy():
293
274
  if handler == self.logger._console and self.logger._support_color:
294
- formatter = ColorStreamFormatter(log_formatprefix, level_format, stream_logformat)
275
+ formatter = SCColorLoggerFormatter(base_format)
295
276
  else:
296
- formatter = LoggerFormatter(log_formatprefix, level_format, stream_logformat)
277
+ formatter = base_format
297
278
  handler.setFormatter(formatter)
298
279
 
299
280
  ###########################################################################
@@ -2867,7 +2848,7 @@ class Chip:
2867
2848
  return hashlist
2868
2849
 
2869
2850
  ###########################################################################
2870
- def dashboard(self, wait=True, port=None, graph_chips=None):
2851
+ def dashboard(self, wait=True, port=None, graph_chips=None, type=DashboardType.WEB):
2871
2852
  '''
2872
2853
  Open a session of the dashboard.
2873
2854
 
@@ -2881,6 +2862,8 @@ class Chip:
2881
2862
  dashboard to.
2882
2863
  graph_chips (list): A list of dictionaries of the format
2883
2864
  {'chip': chip object, 'name': chip name}
2865
+ type (enum): A string specifying what kind of dashboard to
2866
+ launch. Available options: 'cli', 'web'.
2884
2867
 
2885
2868
  Examples:
2886
2869
  >>> chip.dashboard()
@@ -2891,7 +2874,14 @@ class Chip:
2891
2874
  self._dash.stop()
2892
2875
  self._dash = None
2893
2876
 
2894
- self._dash = Dashboard(self, port=port, graph_chips=graph_chips)
2877
+ # Select dashboard type
2878
+ type = DashboardType(type)
2879
+ if type == DashboardType.WEB:
2880
+ self._dash = WebDashboard(self, port=port, graph_chips=graph_chips)
2881
+ elif type == DashboardType.CLI:
2882
+ self._dash = CliDashboard(self)
2883
+ wait = False
2884
+
2895
2885
  self._dash.open_dashboard()
2896
2886
 
2897
2887
  if wait:
@@ -3017,7 +3007,7 @@ class Chip:
3017
3007
  flow (str): Flow name
3018
3008
  step (str): Step name
3019
3009
  task (module/str): Task to associate with this node
3020
- index (int): Step index
3010
+ index (int/str): Step index
3021
3011
 
3022
3012
  Examples:
3023
3013
  >>> import siliconcomiler.tools.openroad.place as place
@@ -3076,8 +3066,8 @@ class Chip:
3076
3066
  flow (str): Name of flow
3077
3067
  tail (str): Name of tail node
3078
3068
  head (str): Name of head node
3079
- tail_index (int): Index of tail node to connect
3080
- head_index (int): Index of head node to connect
3069
+ tail_index (int/str): Index of tail node to connect
3070
+ head_index (int/str): Index of head node to connect
3081
3071
 
3082
3072
  Examples:
3083
3073
  >>> chip.edge('place', 'cts')
@@ -3107,7 +3097,7 @@ class Chip:
3107
3097
  Args:
3108
3098
  flow (str): Flow name
3109
3099
  step (str): Step name
3110
- index (int): Step index
3100
+ index (int/str): Step index
3111
3101
  '''
3112
3102
 
3113
3103
  if flow not in self.getkeys('flowgraph'):
@@ -3219,6 +3209,12 @@ class Chip:
3219
3209
  raise e
3220
3210
  self.logger.error(str(e))
3221
3211
  return False
3212
+ finally:
3213
+ # Update dashboard if running
3214
+ if self._dash:
3215
+ self._dash.update_manifest()
3216
+ self._dash.end_of_run()
3217
+
3222
3218
  return True
3223
3219
 
3224
3220
  ###########################################################################
siliconcompiler/issue.py CHANGED
@@ -273,7 +273,9 @@ def generate_testcase(chip,
273
273
  full_archive_path = os.path.join(archive_directory, archive_name)
274
274
  full_archive_path = os.path.abspath(full_archive_path)
275
275
  # Build archive
276
- arch_base_dir = os.path.basename(archive_name).split('.')[0]
276
+ arch_base_dir = os.path.basename(archive_name)
277
+ while arch_base_dir.lower().split('.')[-1] in ('gz', 'tar'):
278
+ arch_base_dir = '.'.join(arch_base_dir.split('.')[0:-1])
277
279
  with tarfile.open(full_archive_path, "w:gz") as tar:
278
280
  # Add individual files
279
281
  add_files = [manifest_path,
@@ -10,11 +10,12 @@ import tarfile
10
10
  import tempfile
11
11
  import multiprocessing
12
12
 
13
- from siliconcompiler import utils, SiliconCompilerError
13
+ from siliconcompiler import utils, SiliconCompilerError, NodeStatus
14
14
  from siliconcompiler import NodeStatus as SCNodeStatus
15
15
  from siliconcompiler._metadata import default_server
16
16
  from siliconcompiler.flowgraph import nodes_to_execute
17
17
  from siliconcompiler.remote import JobStatus
18
+ from siliconcompiler.report.dashboard import DashboardType
18
19
 
19
20
  # Step name to use while logging
20
21
  remote_step_name = 'remote'
@@ -298,18 +299,19 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
298
299
  self.__logger.info(nodes_log)
299
300
 
300
301
  def _report_job_status(self, info):
302
+ completed = []
303
+ starttimes = {}
304
+
301
305
  if not info['busy']:
302
306
  # Job is not running
303
- return [], False
307
+ return completed, starttimes, False
304
308
 
305
309
  try:
306
310
  # Decode response JSON, if possible.
307
311
  job_info = json.loads(info['message'])
308
312
  except json.JSONDecodeError as e:
309
313
  self.__logger.warning(f"Job is still running: {e}")
310
- return [], True
311
-
312
- completed = []
314
+ return completed, starttimes, True
313
315
 
314
316
  nodes_to_log = {}
315
317
  for node, node_info in job_info.items():
@@ -335,7 +337,16 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
335
337
  self.__log_node_status(stat, nodes)
336
338
 
337
339
  # Running / in-progress flowgraph nodes should all be printed:
340
+ base_time = time.time()
338
341
  for stat, nodes in nodes_to_log.items():
342
+ for node, node_info in nodes:
343
+ if 'elapsed_time' in node_info:
344
+ runtime = 0
345
+ for part in node_info['elapsed_time'].split(":"):
346
+ runtime = 60 * runtime + float(part)
347
+ starttimes[(self.__node_information[node]["step"],
348
+ self.__node_information[node]["index"])] = base_time - runtime
349
+
339
350
  if SCNodeStatus.is_running(stat):
340
351
  self.__logger.info(f' {stat.title()} ({len(nodes)}):')
341
352
  for node, node_info in nodes:
@@ -349,7 +360,7 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
349
360
  if SCNodeStatus.is_waiting(stat):
350
361
  self.__log_node_status(stat, nodes)
351
362
 
352
- return completed, True
363
+ return completed, starttimes, True
353
364
 
354
365
  def __check(self):
355
366
  def post_action(url):
@@ -438,6 +449,9 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
438
449
  raise SiliconCompilerError('Cannot pass [arg,index] parameter into remote flow.',
439
450
  chip=self.__chip)
440
451
 
452
+ if not self.__chip._dash:
453
+ self.__chip.dashboard(type=DashboardType.CLI)
454
+
441
455
  # Only run the pre-process step if the job doesn't already have a remote ID.
442
456
  if not remote_resume:
443
457
  self.__run_preprocess()
@@ -450,10 +464,12 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
450
464
  self.__request_run()
451
465
 
452
466
  # Run the main 'check_progress' loop to monitor job status until it finishes.
453
- self._run_loop()
454
-
455
- # Restore logger
456
- self.__chip._init_logger(in_run=True)
467
+ try:
468
+ self._run_loop()
469
+ finally:
470
+ # Restore logger
471
+ self.__chip._dash.end_of_run()
472
+ self.__chip._init_logger(in_run=True)
457
473
 
458
474
  def __request_run(self):
459
475
  '''
@@ -559,7 +575,7 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
559
575
  self.__logger.info(f'To cancel this job use: {cancel_cmd}')
560
576
  raise SiliconCompilerError('Job canceled by user keyboard interrupt')
561
577
 
562
- def __import_run_manifests(self):
578
+ def __import_run_manifests(self, starttimes):
563
579
  changed = False
564
580
  for _, node_info in self.__node_information.items():
565
581
  if node_info["imported"]:
@@ -577,6 +593,16 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
577
593
  except: # noqa E722
578
594
  # Import may fail if file is still getting written
579
595
  pass
596
+ elif self.__chip.get('record', 'status',
597
+ step=node_info["step"], index=node_info["index"]) \
598
+ == NodeStatus.SKIPPED:
599
+ node_info["imported"] = True
600
+ changed = True
601
+
602
+ if changed and self.__chip._dash:
603
+ # Update dashboard if active
604
+ self.__chip._dash.update_manifest({"starttimes": starttimes})
605
+
580
606
  return changed
581
607
 
582
608
  def __ensure_run_loop_information(self):
@@ -605,17 +631,30 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
605
631
  # Check the job's progress periodically until it finishes.
606
632
  running = True
607
633
 
634
+ starttimes = {}
635
+
608
636
  while running:
609
- time.sleep(self.__check_interval)
610
- self.__import_run_manifests()
637
+ sleepremaining = self.__check_interval
638
+ while any([nodeinfo["fetched"] and not nodeinfo["imported"]
639
+ for nodeinfo in self.__node_information.values()]):
640
+ self.__import_run_manifests(starttimes)
641
+ sleepremaining -= 1
642
+ if sleepremaining <= 0:
643
+ break
644
+ time.sleep(1)
645
+ if sleepremaining > 0:
646
+ time.sleep(sleepremaining)
611
647
 
612
648
  # Check progress
613
649
  job_info = self.check_job_status()
614
- completed, running = self._report_job_status(job_info)
650
+ completed, new_starttimes, running = self._report_job_status(job_info)
651
+
652
+ # preserve old starttimes
653
+ starttimes = {**starttimes, **new_starttimes}
615
654
 
616
655
  if self.__chip._dash:
617
656
  # Update dashboard if active
618
- self.__chip._dash.update_manifest()
657
+ self.__chip._dash.update_manifest({"starttimes": starttimes})
619
658
 
620
659
  nodes_to_fetch = []
621
660
  for node in completed:
@@ -648,7 +687,7 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
648
687
  self.__download_pool.join()
649
688
  self.__download_pool = None
650
689
 
651
- self.__import_run_manifests()
690
+ self.__import_run_manifests({})
652
691
 
653
692
  def __schedule_fetch_result(self, node):
654
693
  self.__node_information[node]["fetched"] = True
@@ -1,7 +1,8 @@
1
1
  from .summary_image import _generate_summary_image, _open_summary_image
2
2
  from .html_report import _generate_html_report, _open_html_report
3
3
  from .summary_table import _show_summary_table
4
- from .dashboard import Dashboard
4
+ from .dashboard.web import WebDashboard
5
+ # from .dashboard import Dashboard
5
6
 
6
7
  __all__ = [
7
8
  "_generate_summary_image",
@@ -9,5 +10,5 @@ __all__ = [
9
10
  "_generate_html_report",
10
11
  "_open_html_report",
11
12
  "_show_summary_table",
12
- "Dashboard"
13
+ "WebDashboard"
13
14
  ]
@@ -1,190 +1,81 @@
1
- import os
2
- import time
3
- import tempfile
4
- import json
1
+ from abc import ABC, abstractmethod
2
+ from enum import Enum
5
3
 
6
- import multiprocessing
7
- import subprocess
8
- import atexit
9
- import shutil
10
- import fasteners
11
- import signal
12
- import socketserver
13
4
 
14
- from siliconcompiler.report.dashboard import utils
5
+ class DashboardType(Enum):
6
+ WEB = 'web'
7
+ CLI = 'cli'
15
8
 
16
- try:
17
- from streamlit.web import bootstrap
18
- from streamlit import config as _config
19
- except ModuleNotFoundError:
20
- bootstrap = None
21
- _config = None
22
9
 
10
+ class AbstractDashboard(ABC):
11
+ """
12
+ Abstract base class defining the interface for dashboard implementations.
13
+ Any concrete dashboard implementation should inherit from this class and
14
+ implement all abstract methods.
15
+ """
23
16
 
24
- class Dashboard():
25
- __port = 8501
17
+ @abstractmethod
18
+ def __init__(self, chip):
19
+ """
20
+ Initialize the dashboard.
26
21
 
27
- @staticmethod
28
- def __signal_handler(signal, frame):
29
- # used to avoid issues during shutdown
30
- pass
31
-
32
- def __init__(self, chip, port=None, graph_chips=None):
33
- if not bootstrap:
34
- raise NotImplementedError('streamlit is not available')
35
-
36
- if not port:
37
- port = Dashboard.get_next_port()
38
- if not port:
39
- port = Dashboard.__port
40
-
41
- self.__dashboard = None
42
- self.__chip = chip
43
- self.__directory = tempfile.mkdtemp(prefix='sc_dashboard_',
44
- suffix=f'_{self.__chip.design}')
45
- self.__manifest = os.path.join(self.__directory, 'manifest.json')
46
- self.__manifest_lock = os.path.join(self.__directory, 'manifest.lock')
47
- self.__port = port
48
- dirname = os.path.dirname(__file__)
49
- self.__streamlit_file = os.path.join(dirname, 'viewer.py')
50
-
51
- self.__streamlit_args = [
52
- ("browser.gatherUsageStats", False),
53
- ("browser.serverPort", self.__port),
54
- ("logger.level", 'error'),
55
- ("runner.fastReruns", True),
56
- ("server.port", self.__port),
57
- ("client.toolbarMode", "viewer")
58
- ]
59
-
60
- # pass in a json object called __graph_chips
61
- # the key is the chip_name and value is the filepath
62
- # if another argument is passed
63
-
64
- # use of list is to preserve order
65
- self.__graph_chips = []
66
- graph_chips_config = []
67
- if graph_chips:
68
- for chip_object_and_name in graph_chips:
69
- chip_file_path = \
70
- os.path.join(self.__directory,
71
- f"{chip_object_and_name['name']}.json")
72
- self.__graph_chips.append({
73
- 'chip': chip_object_and_name['chip'],
74
- 'name': chip_file_path
75
- })
76
- graph_chips_config.append({
77
- "path": chip_file_path,
78
- "cwd": utils.get_chip_cwd(
79
- chip_object_and_name['chip'],
80
- chip_object_and_name['cfg_path'])
81
- })
82
-
83
- self.__config = {
84
- "manifest": self.__manifest,
85
- "lock": self.__manifest_lock,
86
- "graph_chips": graph_chips_config
87
- }
88
-
89
- self.__sleep_time = 0.5
90
- self.__signal_handler = None
91
-
92
- self.__lock = fasteners.InterProcessLock(self.__manifest_lock)
93
-
94
- atexit.register(self.__cleanup)
22
+ Args:
23
+ chip: The chip object to display in the dashboard
24
+ """
25
+ self._chip = chip
95
26
 
27
+ @abstractmethod
96
28
  def open_dashboard(self):
97
- with open(self.__get_config_file(), 'w') as f:
98
- json.dump(self.__config, f, indent=4)
99
-
100
- self.update_manifest()
101
-
102
- self.update_graph_manifests()
103
-
104
- self.__dashboard = multiprocessing.Process(
105
- target=self._run_streamlit_bootstrap)
106
-
107
- self.__signal_handler = signal.signal(signal.SIGINT, Dashboard.__signal_handler)
108
-
109
- self.__dashboard.start()
110
-
111
- def update_manifest(self):
112
- if not self.__manifest:
113
- return
29
+ """
30
+ Open and start the dashboard service.
31
+ """
32
+ pass
114
33
 
115
- new_file = f"{self.__manifest}.new.json"
116
- self.__chip.write_manifest(new_file)
34
+ @abstractmethod
35
+ def update_manifest(self, payload=None):
36
+ """
37
+ Update the manifest file with the latest chip information.
117
38
 
118
- with self.__lock:
119
- shutil.move(new_file, self.__manifest)
39
+ Args:
40
+ payload (dict): Dictionary of metadata to pass along to dashboard.
41
+ {"starttimes" {<node>: time, ...}}
42
+ """
43
+ pass
120
44
 
45
+ @abstractmethod
121
46
  def update_graph_manifests(self):
122
- for chip_object_and_name in self.__graph_chips:
123
- chip = chip_object_and_name['chip']
124
- file_path = chip_object_and_name['name']
125
- chip.write_manifest(file_path)
126
-
127
- def __get_config_file(self):
128
- return os.path.join(self.__directory, 'config.json')
47
+ """
48
+ Update the manifest files for all graph chips.
49
+ """
50
+ pass
129
51
 
52
+ @abstractmethod
130
53
  def is_running(self):
131
- if self.__dashboard is None:
132
- return False
54
+ """
55
+ Check if the dashboard is currently running.
133
56
 
134
- if self.__dashboard.is_alive():
135
- return True
57
+ Returns:
58
+ bool: True if the dashboard is running, False otherwise
59
+ """
60
+ pass
136
61
 
137
- self.__dashboard = None
138
- self.__manifest = None
139
- return False
62
+ @abstractmethod
63
+ def end_of_run(self):
64
+ """
65
+ Announce that a run has completed
66
+ """
67
+ pass
140
68
 
69
+ @abstractmethod
141
70
  def stop(self):
142
- if not self.is_running():
143
- return
144
-
145
- while self.__dashboard.is_alive():
146
- self.__dashboard.terminate()
147
- self._sleep()
148
-
149
- if self.__signal_handler:
150
- signal.signal(signal.SIGINT, self.__signal_handler)
151
-
152
- self.__dashboard = None
153
- self.__manifest = None
154
- self.__signal_handler = None
71
+ """
72
+ Stop the dashboard service if it's running.
73
+ """
74
+ pass
155
75
 
76
+ @abstractmethod
156
77
  def wait(self):
157
- self.__dashboard.join()
158
-
159
- def _sleep(self):
160
- time.sleep(self.__sleep_time)
161
-
162
- def _run_streamlit_bootstrap(self):
163
- for config, val in self.__streamlit_args:
164
- _config.set_option(config, val)
165
-
166
- bootstrap.run(self.__streamlit_file,
167
- False,
168
- [self.__get_config_file()],
169
- flag_options={})
170
-
171
- def __run_streamlit_subproc(self):
172
- cmd = ['streamlit', 'run',
173
- self.__streamlit_file, self.__get_config_file()]
174
- for config, val in self.__streamlit_args:
175
- cmd.append(f'--{config}')
176
- cmd.append(val)
177
-
178
- subprocess.Popen(cmd)
179
-
180
- def __cleanup(self):
181
- self.stop()
182
-
183
- if os.path.exists(self.__directory):
184
- shutil.rmtree(self.__directory)
185
-
186
- @staticmethod
187
- def get_next_port():
188
- with socketserver.TCPServer(("localhost", 0), None) as s:
189
- return s.server_address[1]
190
- return None
78
+ """
79
+ Wait for the dashboard service to terminate.
80
+ """
81
+ pass