siliconcompiler 0.26.5__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 (251) hide show
  1. siliconcompiler/__init__.py +24 -0
  2. siliconcompiler/__main__.py +12 -0
  3. siliconcompiler/_common.py +49 -0
  4. siliconcompiler/_metadata.py +36 -0
  5. siliconcompiler/apps/__init__.py +0 -0
  6. siliconcompiler/apps/_common.py +76 -0
  7. siliconcompiler/apps/sc.py +92 -0
  8. siliconcompiler/apps/sc_dashboard.py +94 -0
  9. siliconcompiler/apps/sc_issue.py +178 -0
  10. siliconcompiler/apps/sc_remote.py +199 -0
  11. siliconcompiler/apps/sc_server.py +39 -0
  12. siliconcompiler/apps/sc_show.py +142 -0
  13. siliconcompiler/apps/smake.py +232 -0
  14. siliconcompiler/checklists/__init__.py +0 -0
  15. siliconcompiler/checklists/oh_tapeout.py +41 -0
  16. siliconcompiler/core.py +3221 -0
  17. siliconcompiler/data/RobotoMono/LICENSE.txt +202 -0
  18. siliconcompiler/data/RobotoMono/RobotoMono-Regular.ttf +0 -0
  19. siliconcompiler/data/heartbeat.v +18 -0
  20. siliconcompiler/data/logo.png +0 -0
  21. siliconcompiler/flowgraph.py +570 -0
  22. siliconcompiler/flows/__init__.py +0 -0
  23. siliconcompiler/flows/_common.py +67 -0
  24. siliconcompiler/flows/asicflow.py +180 -0
  25. siliconcompiler/flows/asictopflow.py +38 -0
  26. siliconcompiler/flows/dvflow.py +86 -0
  27. siliconcompiler/flows/fpgaflow.py +202 -0
  28. siliconcompiler/flows/generate_openroad_rcx.py +66 -0
  29. siliconcompiler/flows/lintflow.py +35 -0
  30. siliconcompiler/flows/screenshotflow.py +51 -0
  31. siliconcompiler/flows/showflow.py +59 -0
  32. siliconcompiler/flows/signoffflow.py +53 -0
  33. siliconcompiler/flows/synflow.py +128 -0
  34. siliconcompiler/fpgas/__init__.py +0 -0
  35. siliconcompiler/fpgas/lattice_ice40.py +42 -0
  36. siliconcompiler/fpgas/vpr_example.py +109 -0
  37. siliconcompiler/issue.py +300 -0
  38. siliconcompiler/libs/__init__.py +0 -0
  39. siliconcompiler/libs/asap7sc7p5t.py +8 -0
  40. siliconcompiler/libs/gf180mcu.py +8 -0
  41. siliconcompiler/libs/nangate45.py +8 -0
  42. siliconcompiler/libs/sky130hd.py +8 -0
  43. siliconcompiler/libs/sky130io.py +8 -0
  44. siliconcompiler/package.py +412 -0
  45. siliconcompiler/pdks/__init__.py +0 -0
  46. siliconcompiler/pdks/asap7.py +8 -0
  47. siliconcompiler/pdks/freepdk45.py +8 -0
  48. siliconcompiler/pdks/gf180.py +8 -0
  49. siliconcompiler/pdks/skywater130.py +8 -0
  50. siliconcompiler/remote/__init__.py +36 -0
  51. siliconcompiler/remote/client.py +891 -0
  52. siliconcompiler/remote/schema.py +106 -0
  53. siliconcompiler/remote/server.py +507 -0
  54. siliconcompiler/remote/server_schema/requests/cancel_job.json +51 -0
  55. siliconcompiler/remote/server_schema/requests/check_progress.json +61 -0
  56. siliconcompiler/remote/server_schema/requests/check_server.json +38 -0
  57. siliconcompiler/remote/server_schema/requests/delete_job.json +51 -0
  58. siliconcompiler/remote/server_schema/requests/get_results.json +48 -0
  59. siliconcompiler/remote/server_schema/requests/remote_run.json +40 -0
  60. siliconcompiler/remote/server_schema/responses/cancel_job.json +18 -0
  61. siliconcompiler/remote/server_schema/responses/check_progress.json +30 -0
  62. siliconcompiler/remote/server_schema/responses/check_server.json +32 -0
  63. siliconcompiler/remote/server_schema/responses/delete_job.json +18 -0
  64. siliconcompiler/remote/server_schema/responses/get_results.json +21 -0
  65. siliconcompiler/remote/server_schema/responses/remote_run.json +25 -0
  66. siliconcompiler/report/__init__.py +13 -0
  67. siliconcompiler/report/html_report.py +74 -0
  68. siliconcompiler/report/report.py +355 -0
  69. siliconcompiler/report/streamlit_report.py +137 -0
  70. siliconcompiler/report/streamlit_viewer.py +944 -0
  71. siliconcompiler/report/summary_image.py +117 -0
  72. siliconcompiler/report/summary_table.py +105 -0
  73. siliconcompiler/report/utils.py +163 -0
  74. siliconcompiler/scheduler/__init__.py +2092 -0
  75. siliconcompiler/scheduler/docker_runner.py +253 -0
  76. siliconcompiler/scheduler/run_node.py +138 -0
  77. siliconcompiler/scheduler/send_messages.py +178 -0
  78. siliconcompiler/scheduler/slurm.py +208 -0
  79. siliconcompiler/scheduler/validation/email_credentials.json +54 -0
  80. siliconcompiler/schema/__init__.py +7 -0
  81. siliconcompiler/schema/schema_cfg.py +4014 -0
  82. siliconcompiler/schema/schema_obj.py +1841 -0
  83. siliconcompiler/schema/utils.py +93 -0
  84. siliconcompiler/sphinx_ext/__init__.py +0 -0
  85. siliconcompiler/sphinx_ext/dynamicgen.py +1006 -0
  86. siliconcompiler/sphinx_ext/schemagen.py +221 -0
  87. siliconcompiler/sphinx_ext/utils.py +166 -0
  88. siliconcompiler/targets/__init__.py +0 -0
  89. siliconcompiler/targets/asap7_demo.py +68 -0
  90. siliconcompiler/targets/asic_demo.py +38 -0
  91. siliconcompiler/targets/fpgaflow_demo.py +47 -0
  92. siliconcompiler/targets/freepdk45_demo.py +59 -0
  93. siliconcompiler/targets/gf180_demo.py +77 -0
  94. siliconcompiler/targets/skywater130_demo.py +70 -0
  95. siliconcompiler/templates/email/general.j2 +66 -0
  96. siliconcompiler/templates/email/summary.j2 +43 -0
  97. siliconcompiler/templates/issue/README.txt +26 -0
  98. siliconcompiler/templates/issue/run.sh +6 -0
  99. siliconcompiler/templates/report/bootstrap.min.css +7 -0
  100. siliconcompiler/templates/report/bootstrap.min.js +7 -0
  101. siliconcompiler/templates/report/bootstrap_LICENSE.md +24 -0
  102. siliconcompiler/templates/report/sc_report.j2 +427 -0
  103. siliconcompiler/templates/slurm/run.sh +9 -0
  104. siliconcompiler/templates/tcl/manifest.tcl.j2 +137 -0
  105. siliconcompiler/tools/__init__.py +0 -0
  106. siliconcompiler/tools/_common/__init__.py +432 -0
  107. siliconcompiler/tools/_common/asic.py +115 -0
  108. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +76 -0
  109. siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +63 -0
  110. siliconcompiler/tools/bambu/bambu.py +32 -0
  111. siliconcompiler/tools/bambu/convert.py +77 -0
  112. siliconcompiler/tools/bluespec/bluespec.py +40 -0
  113. siliconcompiler/tools/bluespec/convert.py +103 -0
  114. siliconcompiler/tools/builtin/_common.py +155 -0
  115. siliconcompiler/tools/builtin/builtin.py +26 -0
  116. siliconcompiler/tools/builtin/concatenate.py +85 -0
  117. siliconcompiler/tools/builtin/join.py +27 -0
  118. siliconcompiler/tools/builtin/maximum.py +46 -0
  119. siliconcompiler/tools/builtin/minimum.py +57 -0
  120. siliconcompiler/tools/builtin/mux.py +70 -0
  121. siliconcompiler/tools/builtin/nop.py +38 -0
  122. siliconcompiler/tools/builtin/verify.py +83 -0
  123. siliconcompiler/tools/chisel/SCDriver.scala +10 -0
  124. siliconcompiler/tools/chisel/build.sbt +27 -0
  125. siliconcompiler/tools/chisel/chisel.py +37 -0
  126. siliconcompiler/tools/chisel/convert.py +140 -0
  127. siliconcompiler/tools/execute/exec_input.py +41 -0
  128. siliconcompiler/tools/execute/execute.py +17 -0
  129. siliconcompiler/tools/genfasm/bitstream.py +61 -0
  130. siliconcompiler/tools/genfasm/genfasm.py +40 -0
  131. siliconcompiler/tools/ghdl/convert.py +87 -0
  132. siliconcompiler/tools/ghdl/ghdl.py +41 -0
  133. siliconcompiler/tools/icarus/compile.py +87 -0
  134. siliconcompiler/tools/icarus/icarus.py +36 -0
  135. siliconcompiler/tools/icepack/bitstream.py +20 -0
  136. siliconcompiler/tools/icepack/icepack.py +43 -0
  137. siliconcompiler/tools/klayout/export.py +117 -0
  138. siliconcompiler/tools/klayout/klayout.py +119 -0
  139. siliconcompiler/tools/klayout/klayout_export.py +205 -0
  140. siliconcompiler/tools/klayout/klayout_operations.py +363 -0
  141. siliconcompiler/tools/klayout/klayout_show.py +242 -0
  142. siliconcompiler/tools/klayout/klayout_utils.py +176 -0
  143. siliconcompiler/tools/klayout/operations.py +194 -0
  144. siliconcompiler/tools/klayout/screenshot.py +98 -0
  145. siliconcompiler/tools/klayout/show.py +101 -0
  146. siliconcompiler/tools/magic/drc.py +49 -0
  147. siliconcompiler/tools/magic/extspice.py +19 -0
  148. siliconcompiler/tools/magic/magic.py +85 -0
  149. siliconcompiler/tools/magic/sc_drc.tcl +96 -0
  150. siliconcompiler/tools/magic/sc_extspice.tcl +54 -0
  151. siliconcompiler/tools/magic/sc_magic.tcl +47 -0
  152. siliconcompiler/tools/montage/montage.py +30 -0
  153. siliconcompiler/tools/montage/tile.py +66 -0
  154. siliconcompiler/tools/netgen/count_lvs.py +132 -0
  155. siliconcompiler/tools/netgen/lvs.py +90 -0
  156. siliconcompiler/tools/netgen/netgen.py +36 -0
  157. siliconcompiler/tools/netgen/sc_lvs.tcl +46 -0
  158. siliconcompiler/tools/nextpnr/apr.py +24 -0
  159. siliconcompiler/tools/nextpnr/nextpnr.py +59 -0
  160. siliconcompiler/tools/openfpgaloader/openfpgaloader.py +39 -0
  161. siliconcompiler/tools/openroad/__init__.py +0 -0
  162. siliconcompiler/tools/openroad/cts.py +45 -0
  163. siliconcompiler/tools/openroad/dfm.py +66 -0
  164. siliconcompiler/tools/openroad/export.py +131 -0
  165. siliconcompiler/tools/openroad/floorplan.py +70 -0
  166. siliconcompiler/tools/openroad/openroad.py +977 -0
  167. siliconcompiler/tools/openroad/physyn.py +27 -0
  168. siliconcompiler/tools/openroad/place.py +41 -0
  169. siliconcompiler/tools/openroad/rcx_bench.py +95 -0
  170. siliconcompiler/tools/openroad/rcx_extract.py +34 -0
  171. siliconcompiler/tools/openroad/route.py +45 -0
  172. siliconcompiler/tools/openroad/screenshot.py +60 -0
  173. siliconcompiler/tools/openroad/scripts/sc_apr.tcl +499 -0
  174. siliconcompiler/tools/openroad/scripts/sc_cts.tcl +64 -0
  175. siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +20 -0
  176. siliconcompiler/tools/openroad/scripts/sc_export.tcl +98 -0
  177. siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +413 -0
  178. siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +158 -0
  179. siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +7 -0
  180. siliconcompiler/tools/openroad/scripts/sc_place.tcl +84 -0
  181. siliconcompiler/tools/openroad/scripts/sc_procs.tcl +423 -0
  182. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +63 -0
  183. siliconcompiler/tools/openroad/scripts/sc_rcx_bench.tcl +20 -0
  184. siliconcompiler/tools/openroad/scripts/sc_rcx_extract.tcl +12 -0
  185. siliconcompiler/tools/openroad/scripts/sc_route.tcl +133 -0
  186. siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +21 -0
  187. siliconcompiler/tools/openroad/scripts/sc_write.tcl +5 -0
  188. siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +361 -0
  189. siliconcompiler/tools/openroad/show.py +94 -0
  190. siliconcompiler/tools/openroad/templates/pex.tcl +8 -0
  191. siliconcompiler/tools/opensta/__init__.py +101 -0
  192. siliconcompiler/tools/opensta/report_libraries.py +28 -0
  193. siliconcompiler/tools/opensta/scripts/sc_procs.tcl +47 -0
  194. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +74 -0
  195. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +268 -0
  196. siliconcompiler/tools/opensta/timing.py +214 -0
  197. siliconcompiler/tools/slang/__init__.py +49 -0
  198. siliconcompiler/tools/slang/lint.py +101 -0
  199. siliconcompiler/tools/surelog/__init__.py +123 -0
  200. siliconcompiler/tools/surelog/parse.py +183 -0
  201. siliconcompiler/tools/surelog/templates/output.v +7 -0
  202. siliconcompiler/tools/sv2v/convert.py +46 -0
  203. siliconcompiler/tools/sv2v/sv2v.py +37 -0
  204. siliconcompiler/tools/template/template.py +125 -0
  205. siliconcompiler/tools/verilator/compile.py +139 -0
  206. siliconcompiler/tools/verilator/lint.py +19 -0
  207. siliconcompiler/tools/verilator/parse.py +27 -0
  208. siliconcompiler/tools/verilator/verilator.py +172 -0
  209. siliconcompiler/tools/vivado/__init__.py +7 -0
  210. siliconcompiler/tools/vivado/bitstream.py +21 -0
  211. siliconcompiler/tools/vivado/place.py +21 -0
  212. siliconcompiler/tools/vivado/route.py +21 -0
  213. siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +6 -0
  214. siliconcompiler/tools/vivado/scripts/sc_place.tcl +2 -0
  215. siliconcompiler/tools/vivado/scripts/sc_route.tcl +4 -0
  216. siliconcompiler/tools/vivado/scripts/sc_run.tcl +45 -0
  217. siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +25 -0
  218. siliconcompiler/tools/vivado/syn_fpga.py +20 -0
  219. siliconcompiler/tools/vivado/vivado.py +147 -0
  220. siliconcompiler/tools/vpr/_json_constraint.py +63 -0
  221. siliconcompiler/tools/vpr/_xml_constraint.py +109 -0
  222. siliconcompiler/tools/vpr/place.py +137 -0
  223. siliconcompiler/tools/vpr/route.py +124 -0
  224. siliconcompiler/tools/vpr/screenshot.py +54 -0
  225. siliconcompiler/tools/vpr/show.py +88 -0
  226. siliconcompiler/tools/vpr/vpr.py +357 -0
  227. siliconcompiler/tools/xyce/xyce.py +36 -0
  228. siliconcompiler/tools/yosys/lec.py +56 -0
  229. siliconcompiler/tools/yosys/prepareLib.py +59 -0
  230. siliconcompiler/tools/yosys/sc_lec.tcl +84 -0
  231. siliconcompiler/tools/yosys/sc_syn.tcl +79 -0
  232. siliconcompiler/tools/yosys/syn_asic.py +565 -0
  233. siliconcompiler/tools/yosys/syn_asic.tcl +377 -0
  234. siliconcompiler/tools/yosys/syn_asic_fpga_shared.tcl +31 -0
  235. siliconcompiler/tools/yosys/syn_fpga.py +146 -0
  236. siliconcompiler/tools/yosys/syn_fpga.tcl +233 -0
  237. siliconcompiler/tools/yosys/syn_strategies.tcl +81 -0
  238. siliconcompiler/tools/yosys/techmaps/lcu_kogge_stone.v +39 -0
  239. siliconcompiler/tools/yosys/templates/abc.const +2 -0
  240. siliconcompiler/tools/yosys/yosys.py +147 -0
  241. siliconcompiler/units.py +259 -0
  242. siliconcompiler/use.py +177 -0
  243. siliconcompiler/utils/__init__.py +423 -0
  244. siliconcompiler/utils/asic.py +158 -0
  245. siliconcompiler/utils/showtools.py +25 -0
  246. siliconcompiler-0.26.5.dist-info/LICENSE +190 -0
  247. siliconcompiler-0.26.5.dist-info/METADATA +195 -0
  248. siliconcompiler-0.26.5.dist-info/RECORD +251 -0
  249. siliconcompiler-0.26.5.dist-info/WHEEL +5 -0
  250. siliconcompiler-0.26.5.dist-info/entry_points.txt +12 -0
  251. siliconcompiler-0.26.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,117 @@
1
+ import os
2
+ import string
3
+ from PIL import Image, ImageFont, ImageDraw
4
+
5
+ from siliconcompiler import units
6
+ from siliconcompiler.report.utils import _find_summary_image, _find_summary_metrics
7
+
8
+
9
+ def _generate_summary_image(chip, output_path):
10
+ '''
11
+ Takes a layout screenshot and generates a design summary image
12
+ featuring a layout thumbnail and several metrics.
13
+ '''
14
+
15
+ img_path = _find_summary_image(chip)
16
+ if not img_path:
17
+ return
18
+
19
+ # Extract metrics for display
20
+ metrics = {
21
+ 'Chip': chip.design,
22
+ }
23
+
24
+ pdk = chip.get('option', 'pdk')
25
+ if pdk:
26
+ metrics['Node'] = pdk
27
+ else:
28
+ fpga_partname = chip.get('fpga', 'partname')
29
+ if fpga_partname:
30
+ metrics['FPGA'] = fpga_partname
31
+
32
+ def format_area(value, unit):
33
+ prefix = units.get_si_prefix(unit)
34
+ mm_area = units.convert(value, from_unit=prefix, to_unit='mm^2')
35
+ if mm_area < 10:
36
+ return units.format_si(value, 'um') + 'um^2'
37
+ else:
38
+ return units.format_si(mm_area, 'mm') + 'mm^2'
39
+
40
+ def format_freq(value, unit):
41
+ value = units.convert(value, from_unit=unit)
42
+ return units.format_si(value, 'Hz') + 'Hz'
43
+
44
+ metrics.update(_find_summary_metrics(chip, {
45
+ 'Area': ('totalarea', format_area),
46
+ 'LUTs': ('luts', None),
47
+ 'Fmax': ('fmax', format_freq)}))
48
+
49
+ # Generate design
50
+
51
+ WIDTH = 1024
52
+ BORDER = 32
53
+ LINE_SPACING = 8
54
+ TEXT_INDENT = 16
55
+
56
+ FONT_PATH = os.path.join(chip.scroot, 'data', 'RobotoMono', 'RobotoMono-Regular.ttf')
57
+ FONT_SIZE = 40
58
+
59
+ # matches dark gray background color configured in klayout_show.py
60
+ BG_COLOR = (33, 33, 33)
61
+
62
+ # near-white
63
+ TEXT_COLOR = (224, 224, 224)
64
+
65
+ original_layout = Image.open(img_path)
66
+ orig_width, orig_height = original_layout.size
67
+
68
+ aspect_ratio = orig_height / orig_width
69
+
70
+ # inset by border left and right
71
+ thumbnail_width = WIDTH - 2 * BORDER
72
+ thumbnail_height = round(thumbnail_width * aspect_ratio)
73
+ layout_thumbnail = original_layout.resize((thumbnail_width, thumbnail_height))
74
+
75
+ font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
76
+
77
+ # Get max height of any ASCII character in font, so we can consistently space each line
78
+ _, descent = font.getmetrics()
79
+ _, bb_top, _, bb_bottom = font.getmask(string.printable).getbbox()
80
+ line_height = (bb_bottom - bb_top) + descent
81
+
82
+ text = []
83
+ x = BORDER + TEXT_INDENT
84
+ y = thumbnail_height + 2 * BORDER
85
+ for metric, value in metrics.items():
86
+ line = f'{metric}: {value}'
87
+
88
+ # shorten line till it fits
89
+ cropped_line = line
90
+ while True:
91
+ line_width = font.getmask(cropped_line).getbbox()[2] + TEXT_INDENT
92
+ if x + line_width < (WIDTH - BORDER):
93
+ break
94
+ cropped_line = cropped_line[:-1]
95
+
96
+ if cropped_line != line:
97
+ chip.logger.warning(f'Cropped {line} to {cropped_line} to fit in design summary '
98
+ 'image')
99
+
100
+ # Stash line to write and coords to write it at
101
+ text.append(((x, y), cropped_line))
102
+
103
+ y += line_height + LINE_SPACING
104
+
105
+ design_summary = Image.new('RGB', (WIDTH, y + BORDER), color=BG_COLOR)
106
+ design_summary.paste(layout_thumbnail, (BORDER, BORDER))
107
+
108
+ draw = ImageDraw.Draw(design_summary)
109
+ for coords, line in text:
110
+ draw.text(coords, line, TEXT_COLOR, font=font)
111
+
112
+ design_summary.save(output_path)
113
+ chip.logger.info(f'Generated summary image at {output_path}')
114
+
115
+
116
+ def _open_summary_image(image):
117
+ Image.open(image).show()
@@ -0,0 +1,105 @@
1
+ import pandas
2
+ import shutil
3
+
4
+ from siliconcompiler.report.utils import _collect_data, _get_flowgraph_path
5
+ from siliconcompiler.tools._common import get_tool_task
6
+ from siliconcompiler.utils import truncate_text
7
+
8
+
9
+ def _show_summary_table(chip, flow, flowgraph_nodes, show_all_indices):
10
+ '''
11
+ Prints the end of run summary table
12
+ '''
13
+
14
+ # Display data
15
+ max_line_width = 135
16
+ column_width = 15
17
+
18
+ max_line_width = max(max_line_width, int(0.9*shutil.get_terminal_size((80, 20)).columns))
19
+
20
+ nodes, _, metrics, metrics_unit, metrics_to_show, _ = \
21
+ _collect_data(chip, flow, flowgraph_nodes)
22
+
23
+ selected_tasks = \
24
+ _get_flowgraph_path(chip, flow, flowgraph_nodes, only_include_successful=True)
25
+
26
+ # only report tool based steps functions
27
+ for (step, index) in list(flowgraph_nodes):
28
+ if get_tool_task(chip, step, index, flow=flow)[0] == 'builtin':
29
+ del flowgraph_nodes[flowgraph_nodes.index((step, index))]
30
+
31
+ if show_all_indices:
32
+ nodes_to_show = nodes
33
+ else:
34
+ nodes_to_show = [n for n in nodes if n in selected_tasks]
35
+
36
+ # Custom reporting modes
37
+ paramlist = []
38
+ for item in chip.getkeys('option', 'param'):
39
+ paramlist.append(item + "=" + chip.get('option', 'param', item))
40
+
41
+ if paramlist:
42
+ paramstr = ', '.join(paramlist)
43
+ else:
44
+ paramstr = "None"
45
+
46
+ # trim labels to column width
47
+ column_labels = []
48
+ labels = [f'{step}{index}' for step, index in nodes_to_show]
49
+ if labels:
50
+ column_width = min([column_width, max([len(label) for label in labels])])
51
+
52
+ for label in labels:
53
+ column_labels.append(truncate_text(label, column_width).center(column_width))
54
+
55
+ row_labels = []
56
+ if metrics_to_show:
57
+ row_label_len = max([len(metric) for metric in metrics_to_show])
58
+ row_unit_len = max([len(metrics_unit[metric]) for metric in metrics_to_show])
59
+ for metric in metrics_to_show:
60
+ row_labels.append(f'{metric:<{row_label_len}} {metrics_unit[metric]:>{row_unit_len}}')
61
+
62
+ data = []
63
+ for metric in metrics_to_show:
64
+ row = []
65
+ for node in nodes_to_show:
66
+ value = metrics[node][metric]
67
+ if value is None:
68
+ value = '---'
69
+ value = ' ' + value.center(column_width)
70
+ row.append(value)
71
+ data.append(row)
72
+
73
+ info_list = ["SUMMARY:\n",
74
+ "design : " + chip.design,
75
+ "params : " + paramstr,
76
+ "jobdir : " + chip.getworkdir()]
77
+
78
+ pdk = chip.get('option', 'pdk')
79
+ if pdk:
80
+ info_list.extend([
81
+ f"foundry : {chip.get('pdk', pdk, 'foundry')}",
82
+ f"process : {pdk}"])
83
+ else:
84
+ fpga_partname = chip.get('fpga', 'partname')
85
+ if fpga_partname:
86
+ info_list.append(f"partname : {fpga_partname}")
87
+
88
+ libraries = set()
89
+ for val, step, index in chip.schema._getvals('asic', 'logiclib'):
90
+ if not step or (step, index) in flowgraph_nodes:
91
+ libraries.update(val)
92
+ if libraries:
93
+ info_list.append(f"targetlibs : {' '.join(libraries)}")
94
+
95
+ info = '\n'.join(info_list)
96
+
97
+ print("-" * max_line_width)
98
+ print(info, "\n")
99
+
100
+ df = pandas.DataFrame(data, row_labels, column_labels)
101
+ if not df.empty:
102
+ print(df.to_string(line_width=max_line_width, col_space=2))
103
+ else:
104
+ print(' No metrics to display!')
105
+ print("-" * max_line_width)
@@ -0,0 +1,163 @@
1
+ from siliconcompiler import NodeStatus
2
+ from siliconcompiler import units
3
+ from siliconcompiler.flowgraph import _get_flowgraph_execution_order, _get_flowgraph_exit_nodes, \
4
+ nodes_to_execute
5
+ from siliconcompiler.tools._common import get_tool_task
6
+
7
+
8
+ def _find_summary_image(chip, ext='png'):
9
+ for nodes in reversed(_get_flowgraph_execution_order(chip, chip.get('option', 'flow'))):
10
+ for step, index in nodes:
11
+ layout_img = chip.find_result(ext, step=step, index=index)
12
+ if layout_img:
13
+ return layout_img
14
+ return None
15
+
16
+
17
+ def _find_summary_metrics(chip, metrics_map):
18
+ metrics = {}
19
+ for nodes in reversed(_get_flowgraph_execution_order(chip, chip.get('option', 'flow'))):
20
+ for step, index in nodes:
21
+ for name, metric_info in metrics_map.items():
22
+ if name in metrics:
23
+ continue
24
+
25
+ metric, formatter = metric_info
26
+
27
+ data = chip.get('metric', metric, step=step, index=index)
28
+ if data is not None:
29
+ unit = None
30
+ if chip.schema.has_field('metric', metric, 'unit'):
31
+ unit = chip.get('metric', metric, field='unit')
32
+ if formatter:
33
+ metrics[name] = formatter(data, unit)
34
+ else:
35
+ metrics[name] = str(data)
36
+
37
+ return metrics
38
+
39
+
40
+ def _collect_data(chip, flow=None, flowgraph_nodes=None, format_as_string=True):
41
+ if not flow:
42
+ flow = chip.get('option', 'flow')
43
+ if not flowgraph_nodes:
44
+ flowgraph_nodes = nodes_to_execute(chip)
45
+ # only report tool based steps functions
46
+ for (step, index) in list(flowgraph_nodes):
47
+ tool, task = get_tool_task(chip, step, '0', flow=flow)
48
+ if tool == 'builtin':
49
+ index = flowgraph_nodes.index((step, index))
50
+ del flowgraph_nodes[index]
51
+ flowgraph_nodes = [
52
+ node for node in flowgraph_nodes
53
+ if chip.get('record', 'status', step=node[0], index=node[1]) != NodeStatus.SKIPPED
54
+ ]
55
+
56
+ # Collections for data
57
+ nodes = []
58
+ errors = {}
59
+ metrics = {}
60
+ metrics_unit = {}
61
+ reports = {}
62
+
63
+ # Build ordered list of nodes in flowgraph
64
+ for level_nodes in _get_flowgraph_execution_order(chip, flow):
65
+ nodes.extend(sorted(level_nodes))
66
+ nodes = [node for node in nodes if node in flowgraph_nodes]
67
+ for (step, index) in nodes:
68
+ metrics[step, index] = {}
69
+ reports[step, index] = {}
70
+
71
+ # Gather data and determine which metrics to show
72
+ # We show a metric if:
73
+ # - at least one step in the steps has a non-zero weight for the metric -OR -
74
+ # at least one step in the steps set a value for it
75
+ metrics_to_show = []
76
+ for metric in chip.getkeys('metric'):
77
+
78
+ # Get the unit associated with the metric
79
+ metric_unit = None
80
+ if chip.schema.has_field('metric', metric, 'unit'):
81
+ metric_unit = chip.get('metric', metric, field='unit')
82
+ metric_type = chip.get('metric', metric, field='type')
83
+
84
+ show_metric = False
85
+ for step, index in nodes:
86
+ if metric in chip.getkeys('flowgraph', flow,
87
+ step, index, 'weight') and \
88
+ chip.get('flowgraph', flow, step, index, 'weight', metric):
89
+ show_metric = True
90
+
91
+ value = chip.get('metric', metric, step=step, index=index)
92
+ if value is not None:
93
+ show_metric = True
94
+ tool, task = get_tool_task(chip, step, index, flow=flow)
95
+ rpts = chip.get('tool', tool, 'task', task, 'report', metric,
96
+ step=step, index=index)
97
+
98
+ errors[step, index] = chip.get('record', 'status', step=step, index=index) == \
99
+ NodeStatus.ERROR
100
+
101
+ if value is not None:
102
+ value = _format_value(metric, value, metric_unit, metric_type, format_as_string)
103
+
104
+ metrics[step, index][metric] = value
105
+ reports[step, index][metric] = rpts
106
+
107
+ if show_metric:
108
+ metrics_to_show.append(metric)
109
+ metrics_unit[metric] = metric_unit if metric_unit else ''
110
+
111
+ if 'totaltime' in metrics_to_show:
112
+ if not any([chip.get('metric', 'totaltime', step=node[0], index=node[1]) is None
113
+ for node in nodes]):
114
+ nodes.sort(
115
+ key=lambda node: chip.get('metric', 'totaltime', step=node[0], index=node[1]))
116
+
117
+ return nodes, errors, metrics, metrics_unit, metrics_to_show, reports
118
+
119
+
120
+ def _format_value(metric, value, metric_unit, metric_type, format_as_string):
121
+ if metric == 'memory':
122
+ if format_as_string:
123
+ return units.format_binary(value, metric_unit)
124
+ value, metric = units.scale_binary(value, metric_unit)
125
+ elif metric in ['exetime', 'tasktime', 'totaltime']:
126
+ if format_as_string:
127
+ return units.format_time(value)
128
+ elif metric_type == 'int':
129
+ if format_as_string:
130
+ return str(value)
131
+ else:
132
+ if format_as_string:
133
+ return units.format_si(value, metric_unit)
134
+ value, metric = units.scale_si(value, metric_unit)
135
+ return value
136
+
137
+
138
+ def _get_flowgraph_path(chip, flow, nodes_to_execute, only_include_successful=False):
139
+ selected_nodes = set()
140
+ to_search = []
141
+ # Start search with any successful leaf nodes.
142
+ flowgraph_steps = list(map(lambda node: node[0], nodes_to_execute))
143
+ end_nodes = _get_flowgraph_exit_nodes(chip, flow, steps=flowgraph_steps)
144
+ for node in end_nodes:
145
+ if only_include_successful:
146
+ if chip.get('record', 'status', step=node[0], index=node[1]) == \
147
+ NodeStatus.SUCCESS:
148
+ selected_nodes.add(node)
149
+ to_search.append(node)
150
+ else:
151
+ selected_nodes.add(node)
152
+ to_search.append(node)
153
+ # Search backwards, saving anything that was selected by leaf nodes.
154
+ while len(to_search) > 0:
155
+ node = to_search.pop(-1)
156
+ input_nodes = chip.get('record', 'inputnode', step=node[0], index=node[1])
157
+ for selected in input_nodes:
158
+ if selected not in selected_nodes:
159
+ selected_nodes.add(selected)
160
+ to_search.append(selected)
161
+
162
+ return [node for node in selected_nodes
163
+ if chip.get('record', 'status', step=node[0], index=node[1]) != NodeStatus.SKIPPED]