siliconcompiler 0.28.2__py3-none-any.whl → 0.28.4__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 (117) hide show
  1. siliconcompiler/_common.py +12 -0
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc_dashboard.py +6 -2
  4. siliconcompiler/apps/sc_install.py +61 -13
  5. siliconcompiler/apps/sc_remote.py +1 -1
  6. siliconcompiler/core.py +132 -68
  7. siliconcompiler/fpgas/vpr_example.py +8 -0
  8. siliconcompiler/package.py +3 -2
  9. siliconcompiler/remote/client.py +41 -10
  10. siliconcompiler/report/__init__.py +1 -1
  11. siliconcompiler/report/{streamlit_report.py → dashboard/__init__.py} +56 -10
  12. siliconcompiler/report/dashboard/components/__init__.py +546 -0
  13. siliconcompiler/report/dashboard/components/flowgraph.py +114 -0
  14. siliconcompiler/report/dashboard/components/graph.py +208 -0
  15. siliconcompiler/report/dashboard/layouts/__init__.py +20 -0
  16. siliconcompiler/report/dashboard/layouts/_common.py +43 -0
  17. siliconcompiler/report/dashboard/layouts/vertical_flowgraph.py +96 -0
  18. siliconcompiler/report/dashboard/layouts/vertical_flowgraph_node_tab.py +117 -0
  19. siliconcompiler/report/dashboard/layouts/vertical_flowgraph_sac_tabs.py +110 -0
  20. siliconcompiler/report/dashboard/state.py +217 -0
  21. siliconcompiler/report/dashboard/utils/__init__.py +73 -0
  22. siliconcompiler/report/dashboard/utils/file_utils.py +120 -0
  23. siliconcompiler/report/dashboard/viewer.py +36 -0
  24. siliconcompiler/report/report.py +22 -4
  25. siliconcompiler/report/summary_table.py +1 -2
  26. siliconcompiler/report/utils.py +1 -2
  27. siliconcompiler/scheduler/__init__.py +45 -6
  28. siliconcompiler/schema/schema_obj.py +4 -2
  29. siliconcompiler/sphinx_ext/dynamicgen.py +6 -0
  30. siliconcompiler/tools/_common/__init__.py +44 -6
  31. siliconcompiler/tools/_common/asic.py +79 -23
  32. siliconcompiler/tools/genfasm/genfasm.py +7 -0
  33. siliconcompiler/tools/ghdl/convert.py +7 -0
  34. siliconcompiler/tools/klayout/convert_drc_db.py +60 -0
  35. siliconcompiler/tools/klayout/drc.py +156 -0
  36. siliconcompiler/tools/klayout/export.py +2 -0
  37. siliconcompiler/tools/klayout/klayout.py +0 -1
  38. siliconcompiler/tools/klayout/klayout_convert_drc_db.py +182 -0
  39. siliconcompiler/tools/klayout/operations.py +2 -0
  40. siliconcompiler/tools/klayout/screenshot.py +2 -0
  41. siliconcompiler/tools/klayout/show.py +4 -4
  42. siliconcompiler/tools/magic/drc.py +21 -0
  43. siliconcompiler/tools/magic/extspice.py +21 -0
  44. siliconcompiler/tools/magic/magic.py +29 -0
  45. siliconcompiler/tools/magic/sc_drc.tcl +2 -12
  46. siliconcompiler/tools/magic/sc_extspice.tcl +3 -15
  47. siliconcompiler/tools/openroad/floorplan.py +5 -0
  48. siliconcompiler/tools/openroad/openroad.py +56 -5
  49. siliconcompiler/tools/openroad/scripts/sc_apr.tcl +15 -0
  50. siliconcompiler/tools/openroad/scripts/sc_cts.tcl +18 -13
  51. siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +61 -10
  52. siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +10 -0
  53. siliconcompiler/tools/openroad/scripts/sc_procs.tcl +31 -1
  54. siliconcompiler/tools/openroad/scripts/sc_route.tcl +8 -2
  55. siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +0 -5
  56. siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +36 -6
  57. siliconcompiler/tools/surelog/__init__.py +12 -0
  58. siliconcompiler/tools/verilator/compile.py +27 -0
  59. siliconcompiler/tools/verilator/verilator.py +9 -0
  60. siliconcompiler/tools/vpr/vpr.py +18 -0
  61. siliconcompiler/tools/yosys/{syn_asic_fpga_shared.tcl → procs.tcl} +23 -0
  62. siliconcompiler/tools/yosys/sc_screenshot.tcl +104 -0
  63. siliconcompiler/tools/yosys/sc_syn.tcl +7 -9
  64. siliconcompiler/tools/yosys/screenshot.py +153 -0
  65. siliconcompiler/tools/yosys/syn_asic.py +3 -0
  66. siliconcompiler/tools/yosys/syn_asic.tcl +1 -3
  67. siliconcompiler/tools/yosys/syn_fpga.tcl +3 -2
  68. siliconcompiler/toolscripts/_tools.json +10 -5
  69. siliconcompiler/toolscripts/rhel8/install-chisel.sh +26 -0
  70. siliconcompiler/toolscripts/rhel8/install-ghdl.sh +25 -0
  71. siliconcompiler/toolscripts/rhel8/install-icarus.sh +40 -0
  72. siliconcompiler/toolscripts/rhel8/install-klayout.sh +17 -0
  73. siliconcompiler/toolscripts/rhel8/install-magic.sh +26 -0
  74. siliconcompiler/toolscripts/rhel8/install-montage.sh +5 -0
  75. siliconcompiler/toolscripts/rhel8/install-netgen.sh +25 -0
  76. siliconcompiler/toolscripts/rhel8/install-openroad.sh +31 -0
  77. siliconcompiler/toolscripts/rhel8/install-slang.sh +31 -0
  78. siliconcompiler/toolscripts/rhel8/install-surelog.sh +32 -0
  79. siliconcompiler/toolscripts/rhel8/install-sv2v.sh +27 -0
  80. siliconcompiler/toolscripts/rhel8/install-verible.sh +24 -0
  81. siliconcompiler/toolscripts/rhel8/install-verilator.sh +40 -0
  82. siliconcompiler/toolscripts/rhel8/install-xyce.sh +64 -0
  83. siliconcompiler/toolscripts/rhel8/install-yosys.sh +23 -0
  84. siliconcompiler/toolscripts/rhel9/install-chisel.sh +26 -0
  85. siliconcompiler/toolscripts/rhel9/install-ghdl.sh +25 -0
  86. siliconcompiler/toolscripts/rhel9/install-icarus.sh +40 -0
  87. siliconcompiler/toolscripts/rhel9/install-klayout.sh +17 -0
  88. siliconcompiler/toolscripts/rhel9/install-magic.sh +26 -0
  89. siliconcompiler/toolscripts/rhel9/install-montage.sh +5 -0
  90. siliconcompiler/toolscripts/rhel9/install-netgen.sh +25 -0
  91. siliconcompiler/toolscripts/rhel9/install-slang.sh +31 -0
  92. siliconcompiler/toolscripts/rhel9/install-surelog.sh +32 -0
  93. siliconcompiler/toolscripts/rhel9/install-sv2v.sh +27 -0
  94. siliconcompiler/toolscripts/rhel9/install-verible.sh +24 -0
  95. siliconcompiler/toolscripts/rhel9/install-verilator.sh +40 -0
  96. siliconcompiler/toolscripts/rhel9/install-xdm.sh +43 -0
  97. siliconcompiler/toolscripts/rhel9/install-xyce.sh +64 -0
  98. siliconcompiler/toolscripts/rhel9/install-yosys.sh +23 -0
  99. siliconcompiler/toolscripts/ubuntu20/install-icepack.sh +1 -1
  100. siliconcompiler/toolscripts/ubuntu20/install-xdm.sh +40 -0
  101. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +2 -2
  102. siliconcompiler/toolscripts/ubuntu22/install-icepack.sh +1 -1
  103. siliconcompiler/toolscripts/ubuntu22/install-xdm.sh +40 -0
  104. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +2 -2
  105. siliconcompiler/toolscripts/ubuntu24/install-icepack.sh +1 -1
  106. siliconcompiler/toolscripts/ubuntu24/install-klayout.sh +2 -0
  107. siliconcompiler/toolscripts/ubuntu24/install-xdm.sh +40 -0
  108. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +2 -2
  109. siliconcompiler/utils/__init__.py +30 -1
  110. siliconcompiler/utils/showtools.py +4 -0
  111. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/METADATA +22 -8
  112. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/RECORD +116 -67
  113. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/WHEEL +1 -1
  114. siliconcompiler/report/streamlit_viewer.py +0 -944
  115. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/LICENSE +0 -0
  116. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/entry_points.txt +0 -0
  117. {siliconcompiler-0.28.2.dist-info → siliconcompiler-0.28.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,110 @@
1
+ import os
2
+ import streamlit
3
+
4
+ from siliconcompiler.report.dashboard import components
5
+ from siliconcompiler.report.dashboard.components import graph
6
+ from siliconcompiler.report.dashboard import state
7
+ from siliconcompiler.report.dashboard import utils
8
+ from siliconcompiler.report.dashboard.utils import file_utils
9
+ from siliconcompiler.report.dashboard.layouts import _common
10
+ import streamlit_antd_components as sac
11
+
12
+
13
+ def layout():
14
+ chip = state.get_chip()
15
+ metric_dataframe, node_to_step_index_map, metric_to_metric_unit_map = \
16
+ utils.generate_metric_dataframe(chip)
17
+
18
+ components.page_header()
19
+
20
+ tab_headings = [
21
+ sac.TabsItem(
22
+ "Metrics",
23
+ icon='stack'),
24
+ sac.TabsItem(
25
+ "Manifest",
26
+ icon=file_utils.get_file_icon('manifest.pkg.json')),
27
+ sac.TabsItem(
28
+ "File Viewer",
29
+ icon=file_utils.get_file_icon(state.get_key(state.SELECTED_FILE))),
30
+ sac.TabsItem(
31
+ "Design Preview",
32
+ icon=file_utils.get_file_icon('design.png'),
33
+ disabled=not os.path.isfile(f'{chip.getworkdir()}/{chip.design}.png')),
34
+ sac.TabsItem(
35
+ "Graphs",
36
+ icon='graph-up',
37
+ disabled=len(state.get_key(state.LOADED_CHIPS)) == 1)
38
+ ]
39
+
40
+ tab_selected = _common.sac_tabs(tab_headings)
41
+
42
+ if tab_selected == "Metrics":
43
+ # Add flowgraph
44
+ if state.get_key(state.DISPLAY_FLOWGRAPH):
45
+ default_flowgraph_width_in_percent = 0.4
46
+ flowgraph_col_width_in_pixels = 520
47
+ flowgraph_col_width_in_percent = \
48
+ state.compute_component_size(
49
+ default_flowgraph_width_in_percent,
50
+ flowgraph_col_width_in_pixels)
51
+
52
+ flowgraph_col, metrics_container = \
53
+ streamlit.columns(
54
+ [flowgraph_col_width_in_percent, 1 - flowgraph_col_width_in_percent],
55
+ gap="large")
56
+
57
+ with flowgraph_col:
58
+ header_col, flowgraph_toggle_container = streamlit.columns(2, gap="large")
59
+ with header_col:
60
+ streamlit.header('Flowgraph')
61
+ components.flowgraph_viewer(chip)
62
+ else:
63
+ flowgraph_toggle_container = streamlit.container()
64
+ metrics_container = streamlit.container()
65
+
66
+ with flowgraph_toggle_container:
67
+ streamlit.markdown("")
68
+ streamlit.markdown("")
69
+
70
+ if state.set_key(state.DISPLAY_FLOWGRAPH, not streamlit.checkbox(
71
+ 'Hide flowgraph',
72
+ help='Click here to hide the flowgraph')):
73
+ state.set_key(state.APP_RERUN, "Flowgraph")
74
+
75
+ with metrics_container:
76
+ components.metrics_viewer(metric_dataframe, metric_to_metric_unit_map)
77
+
78
+ header_col, settings_col = \
79
+ streamlit.columns(
80
+ [0.7, 0.3],
81
+ gap='small')
82
+ with header_col:
83
+ streamlit.header('Node Information')
84
+ with settings_col:
85
+ components.node_selector(list(node_to_step_index_map.keys()))
86
+
87
+ if state.get_selected_node():
88
+ step, index = node_to_step_index_map[state.get_selected_node()]
89
+ current_file = state.get_key(state.SELECTED_FILE)
90
+ components.node_viewer(chip, step, index, metric_dataframe)
91
+ if state.get_key(state.SELECTED_FILE) and \
92
+ current_file != state.get_key(state.SELECTED_FILE):
93
+ state.set_key(state.APP_RERUN, "File")
94
+
95
+ if tab_selected == "Manifest":
96
+ components.manifest_viewer(chip)
97
+
98
+ if tab_selected == "File Viewer":
99
+ components.file_viewer(
100
+ chip,
101
+ state.get_key(state.SELECTED_FILE),
102
+ page_key=state.SELECTED_FILE_PAGE)
103
+
104
+ if tab_selected == "Design Preview":
105
+ components.file_viewer(chip, f'{chip.getworkdir()}/{chip.design}.png')
106
+
107
+ if tab_selected == "Graphs":
108
+ graph.viewer(metric_dataframe, node_to_step_index_map, metric_to_metric_unit_map)
109
+
110
+ _common.check_rerun()
@@ -0,0 +1,217 @@
1
+ import argparse
2
+ import json
3
+ import os
4
+ import streamlit
5
+ import streamlit_javascript
6
+ import fasteners
7
+
8
+ from siliconcompiler import Chip
9
+
10
+
11
+ DISPLAY_FLOWGRAPH = "show_flowgraph"
12
+ SELECTED_JOB = "selected_job"
13
+ SELECTED_NODE = "selected_node"
14
+ # This is needed until the graph supports setting a selected node
15
+ SELECTED_FLOWGRAPH_NODE = "selected_flowgraph_node"
16
+ SELECTED_SELECTOR_NODE = "selected_selector_node"
17
+ NODE_SOURCE = "node_source"
18
+ SELECTED_FILE = "selected_file"
19
+ SELECTED_FILE_PAGE = "selected_file_page"
20
+ LOADED_CHIPS = "loaded_chips"
21
+ UI_WIDTH = "ui_width"
22
+ MANIFEST_FILE = "manifest_file"
23
+ MANIFEST_LOCK = "manifest_lock"
24
+ MANIFEST_TIME = "manifest_time"
25
+ IS_RUNNING = "is_flow_running"
26
+ GRAPH_JOBS = "graph_jobs"
27
+ APP_LAYOUT = "app_layout"
28
+ APP_RERUN = "app_rerun"
29
+ APP_RUNNING_REFRESH = "app_running_refresh"
30
+ APP_STOPPED_REFRESH = "app_stopped_refresh"
31
+ MAX_DICT_ITEMS_TO_SHOW = "max_dict_items"
32
+ MAX_FILE_LINES_TO_SHOW = "max_file_lines"
33
+ SELECT_TAB = "select_tab"
34
+ TAB_INDEX = "tab-index"
35
+ TAB_STATE = "tab-state"
36
+
37
+ _DEBUG = False
38
+ DEVELOPER = False
39
+
40
+
41
+ def _add_default(key, value):
42
+ if key not in streamlit.session_state:
43
+ streamlit.session_state[key] = value
44
+
45
+
46
+ def update_manifest():
47
+ file_time = os.stat(get_key(MANIFEST_FILE)).st_mtime
48
+
49
+ if get_key(MANIFEST_TIME) != file_time:
50
+ chip = Chip(design='')
51
+
52
+ with get_key(MANIFEST_LOCK):
53
+ chip.read_manifest(get_key(MANIFEST_FILE))
54
+ set_key(MANIFEST_TIME, file_time)
55
+ debug_print("Read manifest", get_key(MANIFEST_FILE))
56
+
57
+ add_chip("default", chip)
58
+
59
+ for history in chip.getkeys('history'):
60
+ history_chip = Chip(design='')
61
+ history_chip.schema.cfg = chip.getdict('history', history)
62
+ history_chip.set('design', chip.design)
63
+ add_chip(history, history_chip)
64
+
65
+ return True
66
+ return False
67
+
68
+
69
+ def init():
70
+ _add_default(DISPLAY_FLOWGRAPH, True)
71
+ _add_default(SELECTED_JOB, None)
72
+ _add_default(SELECTED_NODE, None)
73
+ _add_default(SELECTED_FLOWGRAPH_NODE, None)
74
+ _add_default(SELECTED_SELECTOR_NODE, None)
75
+ _add_default(NODE_SOURCE, None)
76
+ _add_default(SELECTED_FILE, None)
77
+ _add_default(SELECTED_FILE_PAGE, None)
78
+ _add_default(LOADED_CHIPS, {})
79
+ _add_default(MANIFEST_FILE, None)
80
+ _add_default(MANIFEST_LOCK, None)
81
+ _add_default(MANIFEST_TIME, None)
82
+ _add_default(IS_RUNNING, False)
83
+ _add_default(GRAPH_JOBS, None)
84
+ _add_default(UI_WIDTH, None)
85
+ _add_default(APP_LAYOUT, "vertical_flowgraph_sac_tabs")
86
+ _add_default(APP_RERUN, None)
87
+ _add_default(APP_RUNNING_REFRESH, 2 * 1000)
88
+ _add_default(APP_STOPPED_REFRESH, 30 * 1000)
89
+ _add_default(MAX_DICT_ITEMS_TO_SHOW, 100)
90
+ _add_default(MAX_FILE_LINES_TO_SHOW, 100)
91
+ _add_default(SELECT_TAB, None)
92
+ _add_default(TAB_INDEX, 0)
93
+
94
+ parser = argparse.ArgumentParser('dashboard')
95
+ parser.add_argument('cfg', nargs='?')
96
+ args = parser.parse_args()
97
+
98
+ if not args.cfg:
99
+ raise ValueError('configuration not provided')
100
+
101
+ if not get_key(LOADED_CHIPS):
102
+ # First time through
103
+
104
+ with open(args.cfg, 'r') as f:
105
+ config = json.load(f)
106
+
107
+ set_key(MANIFEST_FILE, config["manifest"])
108
+ set_key(MANIFEST_LOCK, fasteners.InterProcessLock(config["lock"]))
109
+
110
+ update_manifest()
111
+ chip = get_chip("default")
112
+ for graph_info in config['graph_chips']:
113
+ file_path = graph_info['path']
114
+ graph_chip = Chip(design='')
115
+ graph_chip.read_manifest(file_path)
116
+ graph_chip.unset('arg', 'step')
117
+ graph_chip.unset('arg', 'index')
118
+
119
+ if graph_info['cwd']:
120
+ graph_chip.cwd = graph_info['cwd']
121
+
122
+ add_chip(os.path.basename(file_path), graph_chip)
123
+
124
+ chip_step = chip.get('arg', 'step')
125
+ chip_index = chip.get('arg', 'index')
126
+
127
+ if chip_step and chip_index:
128
+ set_key(SELECTED_NODE, f'{chip_step}{chip_index}')
129
+
130
+ chip = get_chip("default")
131
+ chip.unset('arg', 'step')
132
+ chip.unset('arg', 'index')
133
+
134
+ if not get_key(SELECTED_JOB):
135
+ set_key(SELECTED_JOB, "default")
136
+
137
+
138
+ def setup():
139
+ with streamlit.empty():
140
+ # get width
141
+ set_key(UI_WIDTH, streamlit_javascript.st_javascript("window.innerWidth"))
142
+ # replace with a empty container to avoid adding a gap at the top
143
+ streamlit.empty()
144
+
145
+ set_key(NODE_SOURCE, None)
146
+
147
+
148
+ def get_chip(job=None):
149
+ if not job:
150
+ job = get_key(SELECTED_JOB)
151
+ return get_key(LOADED_CHIPS)[job]
152
+
153
+
154
+ def add_chip(name, chip):
155
+ streamlit.session_state[LOADED_CHIPS][name] = chip
156
+
157
+
158
+ def get_chips():
159
+ chips = list(get_key(LOADED_CHIPS).keys())
160
+ chips.remove('default')
161
+ chips.insert(0, 'default')
162
+ return chips
163
+
164
+
165
+ def get_selected_node():
166
+ if get_key(NODE_SOURCE) == "flowgraph":
167
+ return get_key(SELECTED_FLOWGRAPH_NODE)
168
+
169
+ if get_key(NODE_SOURCE) == "selector":
170
+ return get_key(SELECTED_SELECTOR_NODE)
171
+
172
+ return get_key(SELECTED_NODE)
173
+
174
+
175
+ def get_key(key):
176
+ return streamlit.session_state[key]
177
+
178
+
179
+ def set_key(key, value):
180
+ changed = value != streamlit.session_state[key]
181
+ if changed:
182
+ debug_print("set_key()", key, "changed", streamlit.session_state[key], "->", value)
183
+ streamlit.session_state[key] = value
184
+ return True
185
+ return False
186
+
187
+
188
+ def del_key(key):
189
+ debug_print("del_key()", key)
190
+ if key in streamlit.session_state:
191
+ del streamlit.session_state[key]
192
+
193
+
194
+ def compute_component_size(minimum, requested_px):
195
+ ui_width = get_key(UI_WIDTH)
196
+
197
+ if ui_width > 0:
198
+ return min(requested_px / ui_width, minimum)
199
+
200
+ return minimum
201
+
202
+
203
+ def debug_print(*args):
204
+ if not _DEBUG:
205
+ return
206
+
207
+ print(*args)
208
+
209
+
210
+ def debug_print_state():
211
+ if not _DEBUG:
212
+ return
213
+
214
+ for n, key in enumerate(sorted(streamlit.session_state.keys())):
215
+ value = streamlit.session_state[key]
216
+ print("state", n, key, type(value), value)
217
+ print()
@@ -0,0 +1,73 @@
1
+ from siliconcompiler import NodeStatus
2
+ from siliconcompiler.flowgraph import _get_flowgraph_nodes
3
+
4
+ from pathlib import Path
5
+
6
+
7
+ def get_chip_cwd(chip, manifest):
8
+ build_dir = Path(chip.get('option', 'builddir'))
9
+
10
+ manifest_path = Path(manifest)
11
+ for path in manifest_path.parents:
12
+ if build_dir.name == path.name:
13
+ return str(path.parent)
14
+
15
+ return None
16
+
17
+
18
+ def make_node_to_step_index_map(chip, metric_dataframe):
19
+ '''
20
+ Returns a map from the name of a node to the associated step, index pair.
21
+
22
+ Args:
23
+ metric_dataframe (pandas.DataFrame) : A dataframe full of all metrics and all
24
+ nodes of the selected chip
25
+ '''
26
+ node_to_step_index_map = {}
27
+ for step, index in _get_flowgraph_nodes(chip, chip.get('option', 'flow')):
28
+ node_to_step_index_map[f'{step}{index}'] = (step, index)
29
+
30
+ # concatenate step and index
31
+ metric_dataframe.columns = metric_dataframe.columns.map(lambda x: f'{x[0]}{x[1]}')
32
+ return node_to_step_index_map, metric_dataframe
33
+
34
+
35
+ def make_metric_to_metric_unit_map(metric_dataframe):
36
+ '''
37
+ Returns a map from the name of a metric to the associated metric and unit in
38
+ the form f'{x[0]} ({x[1]})'
39
+
40
+ Args:
41
+ metric_dataframe (pandas.DataFrame) : A dataframe full of all metrics and all
42
+ nodes of the selected chip.
43
+ '''
44
+ metric_to_metric_unit_map = {}
45
+ for metric, unit in metric_dataframe.index.tolist():
46
+ if unit != '':
47
+ metric_to_metric_unit_map[f'{metric} ({unit})'] = metric
48
+ else:
49
+ metric_to_metric_unit_map[metric] = metric
50
+ # concatenate metric and unit
51
+ metric_dataframe.index = metric_dataframe.index.map(lambda x: f'{x[0]} ({x[1]})'
52
+ if x[1] else x[0])
53
+ return metric_to_metric_unit_map, metric_dataframe
54
+
55
+
56
+ def is_running(chip):
57
+ for step, index in _get_flowgraph_nodes(chip, chip.get('option', 'flow')):
58
+ state = chip.get('record', 'status', step=step, index=index)
59
+ if not NodeStatus.is_done(state):
60
+ return True
61
+ return False
62
+
63
+
64
+ def generate_metric_dataframe(chip):
65
+ from siliconcompiler.report import report
66
+
67
+ metric_dataframe = report.make_metric_dataframe(chip)
68
+ node_to_step_index_map, metric_dataframe = \
69
+ make_node_to_step_index_map(chip, metric_dataframe)
70
+ metric_to_metric_unit_map, metric_dataframe = \
71
+ make_metric_to_metric_unit_map(metric_dataframe)
72
+
73
+ return metric_dataframe, node_to_step_index_map, metric_to_metric_unit_map
@@ -0,0 +1,120 @@
1
+ import gzip
2
+ import os
3
+ from siliconcompiler import utils, sc_open
4
+
5
+
6
+ def is_file_is_binary(path, compressed):
7
+ # Read first chunk and check for non characters
8
+ try:
9
+ if compressed:
10
+ with gzip.open(path, 'rt') as f:
11
+ f.read(8196)
12
+ else:
13
+ with open(path, "r") as f:
14
+ f.read(8196)
15
+ except UnicodeDecodeError:
16
+ return True
17
+ return False
18
+
19
+
20
+ def read_file(path, max_lines):
21
+ _, compressed_file_extension = os.path.splitext(path.lower())
22
+ file_info = []
23
+ honor_max_file = max_lines is not None
24
+
25
+ def read_file(fid):
26
+ for line in fid:
27
+ file_info.append(line.rstrip())
28
+ if honor_max_file and len(file_info) >= max_lines:
29
+ file_info.append('... truncated ...')
30
+ return
31
+
32
+ is_compressed = compressed_file_extension == '.gz'
33
+ if is_file_is_binary(path, is_compressed):
34
+ return "Binary file"
35
+
36
+ if is_compressed:
37
+ with gzip.open(path, 'rt') as fid:
38
+ read_file(fid)
39
+ else:
40
+ with sc_open(path) as fid:
41
+ read_file(fid)
42
+ return "\n".join(file_info)
43
+
44
+
45
+ def get_file_type(ext):
46
+ if ext in ("v", "vh", "sv", "svh", "vg"):
47
+ return "verilog"
48
+ if ext in ("vhdl", "vhd"):
49
+ return "vhdl"
50
+ if ext in ("tcl", "sdc", "xdc"):
51
+ return "tcl"
52
+ if ext in ("c", "cpp", "cc", "h"):
53
+ return "cpp"
54
+ if ext in ("csv",):
55
+ return "csv"
56
+ if ext in ("md",):
57
+ return "markdown"
58
+ if ext in ("sh",):
59
+ return "bash"
60
+ return "log"
61
+
62
+
63
+ def get_file_icon(file):
64
+ if not file:
65
+ return 'file'
66
+ ext = utils.get_file_ext(file)
67
+ file_type = get_file_type(ext)
68
+ if file.endswith('.pkg.json'):
69
+ return 'boxes'
70
+ elif ext in ('png', 'jpg', 'jpeg'):
71
+ return 'file-image'
72
+ elif ext == 'json':
73
+ return 'file-json'
74
+ elif file_type in ('verilog', 'tcl', 'vhdl', 'cpp', 'bash'):
75
+ return 'file-code'
76
+ elif ext in ('log', 'rpt', 'drc', 'warnings', 'errors'):
77
+ return 'file-text'
78
+ return 'file'
79
+
80
+
81
+ def convert_filepaths_to_select_tree(logs_and_reports):
82
+ """
83
+ Converts the logs_and_reports found to the structure
84
+ required by streamlit_tree_select. Success is predicated on the order of
85
+ logs_and_reports outlined in report.get_files.
86
+
87
+ Args:
88
+ logs_and_reports (list) : A list of 3-tuples with order of a path name,
89
+ folder in the..., and files in the....
90
+ """
91
+ if not logs_and_reports:
92
+ return []
93
+
94
+ all_files = {}
95
+ for path_name, folders, files in logs_and_reports:
96
+ all_files[path_name] = {
97
+ 'files': list(files),
98
+ 'folders': list(folders)
99
+ }
100
+
101
+ def organize_node(base_folder):
102
+ nodes = []
103
+
104
+ for folder in all_files[base_folder]['folders']:
105
+ path = os.path.join(base_folder, folder)
106
+ nodes.append({
107
+ 'value': path,
108
+ 'label': folder,
109
+ 'children': organize_node(path)
110
+ })
111
+ for file in all_files[base_folder]['files']:
112
+ nodes.append({
113
+ 'value': os.path.join(base_folder, file),
114
+ 'label': file
115
+ })
116
+
117
+ return nodes
118
+
119
+ starting_path_name = logs_and_reports[0][0]
120
+ return organize_node(starting_path_name)
@@ -0,0 +1,36 @@
1
+ import streamlit
2
+
3
+ from siliconcompiler.report.dashboard import components
4
+ from siliconcompiler.report.dashboard import layouts
5
+ from siliconcompiler.report.dashboard import state
6
+ from siliconcompiler.report.dashboard import utils
7
+
8
+ import streamlit_autorefresh
9
+
10
+
11
+ if __name__ == "__main__":
12
+ # opened by running command in siliconcompiler/apps/sc_dashboard.py
13
+ state.init()
14
+
15
+ components.setup_page()
16
+ state.setup()
17
+
18
+ layout = layouts.get_layout(state.get_key(state.APP_LAYOUT))
19
+ layout()
20
+
21
+ reload = False
22
+ if state.get_key(state.SELECTED_JOB) == 'default':
23
+ reload = state.set_key(state.IS_RUNNING, utils.is_running(state.get_chip()))
24
+
25
+ if state.get_key(state.IS_RUNNING):
26
+ update_interval = state.get_key(state.APP_RUNNING_REFRESH)
27
+ else:
28
+ update_interval = state.get_key(state.APP_STOPPED_REFRESH)
29
+
30
+ streamlit_autorefresh.st_autorefresh(interval=update_interval)
31
+
32
+ state.debug_print_state()
33
+
34
+ if reload or state.update_manifest() or state.get_key(state.APP_RERUN):
35
+ state.set_key(state.APP_RERUN, None)
36
+ streamlit.rerun()
@@ -1,3 +1,4 @@
1
+ import fnmatch
1
2
  import pandas
2
3
  import os
3
4
  from siliconcompiler import Schema
@@ -104,7 +105,8 @@ def make_manifest_helper(manifest_subsect, modified_manifest_subsect):
104
105
 
105
106
  def build_leaf(manifest_subsect):
106
107
  if manifest_subsect['pernode'] == 'never':
107
- if Schema.GLOBAL_KEY in manifest_subsect['node']:
108
+ if Schema.GLOBAL_KEY in manifest_subsect['node'] and \
109
+ Schema.GLOBAL_KEY in manifest_subsect['node'][Schema.GLOBAL_KEY]:
108
110
  value = manifest_subsect['node'][Schema.GLOBAL_KEY][Schema.GLOBAL_KEY]['value']
109
111
  else:
110
112
  value = manifest_subsect['node']['default']['default']['value']
@@ -201,7 +203,7 @@ def search_manifest_keys(manifest, key):
201
203
  '''
202
204
  filtered_manifest = {}
203
205
  for dict_key in manifest:
204
- if key in dict_key:
206
+ if fnmatch.fnmatch(dict_key, key):
205
207
  filtered_manifest[dict_key] = manifest[dict_key]
206
208
  elif isinstance(manifest[dict_key], dict):
207
209
  result = search_manifest_keys(manifest[dict_key], key)
@@ -225,8 +227,16 @@ def search_manifest_values(manifest, value):
225
227
  result = search_manifest_values(manifest[key], value)
226
228
  if result: # result is non-empty
227
229
  filtered_manifest[key] = result
228
- elif isinstance(manifest[key], str) and value in manifest[key]:
229
- filtered_manifest[key] = manifest[key]
230
+ else:
231
+ if manifest[key] is None:
232
+ continue
233
+
234
+ if isinstance(manifest[key], (list, tuple)):
235
+ if fnmatch.filter([str(v) for v in manifest[key]], value):
236
+ filtered_manifest[key] = manifest[key]
237
+ else:
238
+ if fnmatch.fnmatch(str(manifest[key]), value):
239
+ filtered_manifest[key] = manifest[key]
230
240
  return filtered_manifest
231
241
 
232
242
 
@@ -251,8 +261,12 @@ def search_manifest(manifest, key_search=None, value_search=None):
251
261
  '''
252
262
  return_manifest = manifest
253
263
  if key_search:
264
+ if '*' not in key_search or '?' not in key_search:
265
+ key_search = f'*{key_search}*'
254
266
  return_manifest = search_manifest_keys(return_manifest, key_search)
255
267
  if value_search:
268
+ if '*' not in value_search or '?' not in value_search:
269
+ value_search = f'*{value_search}*'
256
270
  return_manifest = search_manifest_values(return_manifest, value_search)
257
271
  return return_manifest
258
272
 
@@ -286,7 +300,11 @@ def get_metrics_source(chip, step, index):
286
300
  '''
287
301
  file_to_metric = {}
288
302
  tool, task = get_tool_task(chip, step, index)
303
+ if not chip.valid('tool', tool, 'task', task, 'report'):
304
+ return file_to_metric
305
+
289
306
  metrics = chip.getkeys('tool', tool, 'task', task, 'report')
307
+
290
308
  for metric in metrics:
291
309
  sources = chip.get('tool', tool, 'task', task, 'report', metric, step=step, index=index)
292
310
  for source in sources:
@@ -12,10 +12,9 @@ def _show_summary_table(chip, flow, flowgraph_nodes, show_all_indices):
12
12
  '''
13
13
 
14
14
  # Display data
15
- max_line_width = 135
16
15
  column_width = 15
17
16
 
18
- max_line_width = max(max_line_width, int(0.9*shutil.get_terminal_size((80, 20)).columns))
17
+ max_line_width = max(2 * column_width, int(0.95*shutil.get_terminal_size().columns))
19
18
 
20
19
  nodes, _, metrics, metrics_unit, metrics_to_show, _ = \
21
20
  _collect_data(chip, flow, flowgraph_nodes)
@@ -143,8 +143,7 @@ def _get_flowgraph_path(chip, flow, nodes_to_execute, only_include_successful=Fa
143
143
  end_nodes = _get_flowgraph_exit_nodes(chip, flow, steps=flowgraph_steps)
144
144
  for node in end_nodes:
145
145
  if only_include_successful:
146
- if chip.get('record', 'status', step=node[0], index=node[1]) == \
147
- NodeStatus.SUCCESS:
146
+ if NodeStatus.is_success(chip.get('record', 'status', step=node[0], index=node[1])):
148
147
  selected_nodes.add(node)
149
148
  to_search.append(node)
150
149
  else: