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.
- siliconcompiler/__init__.py +24 -0
- siliconcompiler/__main__.py +12 -0
- siliconcompiler/_common.py +49 -0
- siliconcompiler/_metadata.py +36 -0
- siliconcompiler/apps/__init__.py +0 -0
- siliconcompiler/apps/_common.py +76 -0
- siliconcompiler/apps/sc.py +92 -0
- siliconcompiler/apps/sc_dashboard.py +94 -0
- siliconcompiler/apps/sc_issue.py +178 -0
- siliconcompiler/apps/sc_remote.py +199 -0
- siliconcompiler/apps/sc_server.py +39 -0
- siliconcompiler/apps/sc_show.py +142 -0
- siliconcompiler/apps/smake.py +232 -0
- siliconcompiler/checklists/__init__.py +0 -0
- siliconcompiler/checklists/oh_tapeout.py +41 -0
- siliconcompiler/core.py +3221 -0
- siliconcompiler/data/RobotoMono/LICENSE.txt +202 -0
- siliconcompiler/data/RobotoMono/RobotoMono-Regular.ttf +0 -0
- siliconcompiler/data/heartbeat.v +18 -0
- siliconcompiler/data/logo.png +0 -0
- siliconcompiler/flowgraph.py +570 -0
- siliconcompiler/flows/__init__.py +0 -0
- siliconcompiler/flows/_common.py +67 -0
- siliconcompiler/flows/asicflow.py +180 -0
- siliconcompiler/flows/asictopflow.py +38 -0
- siliconcompiler/flows/dvflow.py +86 -0
- siliconcompiler/flows/fpgaflow.py +202 -0
- siliconcompiler/flows/generate_openroad_rcx.py +66 -0
- siliconcompiler/flows/lintflow.py +35 -0
- siliconcompiler/flows/screenshotflow.py +51 -0
- siliconcompiler/flows/showflow.py +59 -0
- siliconcompiler/flows/signoffflow.py +53 -0
- siliconcompiler/flows/synflow.py +128 -0
- siliconcompiler/fpgas/__init__.py +0 -0
- siliconcompiler/fpgas/lattice_ice40.py +42 -0
- siliconcompiler/fpgas/vpr_example.py +109 -0
- siliconcompiler/issue.py +300 -0
- siliconcompiler/libs/__init__.py +0 -0
- siliconcompiler/libs/asap7sc7p5t.py +8 -0
- siliconcompiler/libs/gf180mcu.py +8 -0
- siliconcompiler/libs/nangate45.py +8 -0
- siliconcompiler/libs/sky130hd.py +8 -0
- siliconcompiler/libs/sky130io.py +8 -0
- siliconcompiler/package.py +412 -0
- siliconcompiler/pdks/__init__.py +0 -0
- siliconcompiler/pdks/asap7.py +8 -0
- siliconcompiler/pdks/freepdk45.py +8 -0
- siliconcompiler/pdks/gf180.py +8 -0
- siliconcompiler/pdks/skywater130.py +8 -0
- siliconcompiler/remote/__init__.py +36 -0
- siliconcompiler/remote/client.py +891 -0
- siliconcompiler/remote/schema.py +106 -0
- siliconcompiler/remote/server.py +507 -0
- siliconcompiler/remote/server_schema/requests/cancel_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/check_progress.json +61 -0
- siliconcompiler/remote/server_schema/requests/check_server.json +38 -0
- siliconcompiler/remote/server_schema/requests/delete_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/get_results.json +48 -0
- siliconcompiler/remote/server_schema/requests/remote_run.json +40 -0
- siliconcompiler/remote/server_schema/responses/cancel_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/check_progress.json +30 -0
- siliconcompiler/remote/server_schema/responses/check_server.json +32 -0
- siliconcompiler/remote/server_schema/responses/delete_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/get_results.json +21 -0
- siliconcompiler/remote/server_schema/responses/remote_run.json +25 -0
- siliconcompiler/report/__init__.py +13 -0
- siliconcompiler/report/html_report.py +74 -0
- siliconcompiler/report/report.py +355 -0
- siliconcompiler/report/streamlit_report.py +137 -0
- siliconcompiler/report/streamlit_viewer.py +944 -0
- siliconcompiler/report/summary_image.py +117 -0
- siliconcompiler/report/summary_table.py +105 -0
- siliconcompiler/report/utils.py +163 -0
- siliconcompiler/scheduler/__init__.py +2092 -0
- siliconcompiler/scheduler/docker_runner.py +253 -0
- siliconcompiler/scheduler/run_node.py +138 -0
- siliconcompiler/scheduler/send_messages.py +178 -0
- siliconcompiler/scheduler/slurm.py +208 -0
- siliconcompiler/scheduler/validation/email_credentials.json +54 -0
- siliconcompiler/schema/__init__.py +7 -0
- siliconcompiler/schema/schema_cfg.py +4014 -0
- siliconcompiler/schema/schema_obj.py +1841 -0
- siliconcompiler/schema/utils.py +93 -0
- siliconcompiler/sphinx_ext/__init__.py +0 -0
- siliconcompiler/sphinx_ext/dynamicgen.py +1006 -0
- siliconcompiler/sphinx_ext/schemagen.py +221 -0
- siliconcompiler/sphinx_ext/utils.py +166 -0
- siliconcompiler/targets/__init__.py +0 -0
- siliconcompiler/targets/asap7_demo.py +68 -0
- siliconcompiler/targets/asic_demo.py +38 -0
- siliconcompiler/targets/fpgaflow_demo.py +47 -0
- siliconcompiler/targets/freepdk45_demo.py +59 -0
- siliconcompiler/targets/gf180_demo.py +77 -0
- siliconcompiler/targets/skywater130_demo.py +70 -0
- siliconcompiler/templates/email/general.j2 +66 -0
- siliconcompiler/templates/email/summary.j2 +43 -0
- siliconcompiler/templates/issue/README.txt +26 -0
- siliconcompiler/templates/issue/run.sh +6 -0
- siliconcompiler/templates/report/bootstrap.min.css +7 -0
- siliconcompiler/templates/report/bootstrap.min.js +7 -0
- siliconcompiler/templates/report/bootstrap_LICENSE.md +24 -0
- siliconcompiler/templates/report/sc_report.j2 +427 -0
- siliconcompiler/templates/slurm/run.sh +9 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +137 -0
- siliconcompiler/tools/__init__.py +0 -0
- siliconcompiler/tools/_common/__init__.py +432 -0
- siliconcompiler/tools/_common/asic.py +115 -0
- siliconcompiler/tools/_common/sdc/sc_constraints.sdc +76 -0
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +63 -0
- siliconcompiler/tools/bambu/bambu.py +32 -0
- siliconcompiler/tools/bambu/convert.py +77 -0
- siliconcompiler/tools/bluespec/bluespec.py +40 -0
- siliconcompiler/tools/bluespec/convert.py +103 -0
- siliconcompiler/tools/builtin/_common.py +155 -0
- siliconcompiler/tools/builtin/builtin.py +26 -0
- siliconcompiler/tools/builtin/concatenate.py +85 -0
- siliconcompiler/tools/builtin/join.py +27 -0
- siliconcompiler/tools/builtin/maximum.py +46 -0
- siliconcompiler/tools/builtin/minimum.py +57 -0
- siliconcompiler/tools/builtin/mux.py +70 -0
- siliconcompiler/tools/builtin/nop.py +38 -0
- siliconcompiler/tools/builtin/verify.py +83 -0
- siliconcompiler/tools/chisel/SCDriver.scala +10 -0
- siliconcompiler/tools/chisel/build.sbt +27 -0
- siliconcompiler/tools/chisel/chisel.py +37 -0
- siliconcompiler/tools/chisel/convert.py +140 -0
- siliconcompiler/tools/execute/exec_input.py +41 -0
- siliconcompiler/tools/execute/execute.py +17 -0
- siliconcompiler/tools/genfasm/bitstream.py +61 -0
- siliconcompiler/tools/genfasm/genfasm.py +40 -0
- siliconcompiler/tools/ghdl/convert.py +87 -0
- siliconcompiler/tools/ghdl/ghdl.py +41 -0
- siliconcompiler/tools/icarus/compile.py +87 -0
- siliconcompiler/tools/icarus/icarus.py +36 -0
- siliconcompiler/tools/icepack/bitstream.py +20 -0
- siliconcompiler/tools/icepack/icepack.py +43 -0
- siliconcompiler/tools/klayout/export.py +117 -0
- siliconcompiler/tools/klayout/klayout.py +119 -0
- siliconcompiler/tools/klayout/klayout_export.py +205 -0
- siliconcompiler/tools/klayout/klayout_operations.py +363 -0
- siliconcompiler/tools/klayout/klayout_show.py +242 -0
- siliconcompiler/tools/klayout/klayout_utils.py +176 -0
- siliconcompiler/tools/klayout/operations.py +194 -0
- siliconcompiler/tools/klayout/screenshot.py +98 -0
- siliconcompiler/tools/klayout/show.py +101 -0
- siliconcompiler/tools/magic/drc.py +49 -0
- siliconcompiler/tools/magic/extspice.py +19 -0
- siliconcompiler/tools/magic/magic.py +85 -0
- siliconcompiler/tools/magic/sc_drc.tcl +96 -0
- siliconcompiler/tools/magic/sc_extspice.tcl +54 -0
- siliconcompiler/tools/magic/sc_magic.tcl +47 -0
- siliconcompiler/tools/montage/montage.py +30 -0
- siliconcompiler/tools/montage/tile.py +66 -0
- siliconcompiler/tools/netgen/count_lvs.py +132 -0
- siliconcompiler/tools/netgen/lvs.py +90 -0
- siliconcompiler/tools/netgen/netgen.py +36 -0
- siliconcompiler/tools/netgen/sc_lvs.tcl +46 -0
- siliconcompiler/tools/nextpnr/apr.py +24 -0
- siliconcompiler/tools/nextpnr/nextpnr.py +59 -0
- siliconcompiler/tools/openfpgaloader/openfpgaloader.py +39 -0
- siliconcompiler/tools/openroad/__init__.py +0 -0
- siliconcompiler/tools/openroad/cts.py +45 -0
- siliconcompiler/tools/openroad/dfm.py +66 -0
- siliconcompiler/tools/openroad/export.py +131 -0
- siliconcompiler/tools/openroad/floorplan.py +70 -0
- siliconcompiler/tools/openroad/openroad.py +977 -0
- siliconcompiler/tools/openroad/physyn.py +27 -0
- siliconcompiler/tools/openroad/place.py +41 -0
- siliconcompiler/tools/openroad/rcx_bench.py +95 -0
- siliconcompiler/tools/openroad/rcx_extract.py +34 -0
- siliconcompiler/tools/openroad/route.py +45 -0
- siliconcompiler/tools/openroad/screenshot.py +60 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +499 -0
- siliconcompiler/tools/openroad/scripts/sc_cts.tcl +64 -0
- siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_export.tcl +98 -0
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +413 -0
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +158 -0
- siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +7 -0
- siliconcompiler/tools/openroad/scripts/sc_place.tcl +84 -0
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +423 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +63 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_bench.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_extract.tcl +12 -0
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +133 -0
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +21 -0
- siliconcompiler/tools/openroad/scripts/sc_write.tcl +5 -0
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +361 -0
- siliconcompiler/tools/openroad/show.py +94 -0
- siliconcompiler/tools/openroad/templates/pex.tcl +8 -0
- siliconcompiler/tools/opensta/__init__.py +101 -0
- siliconcompiler/tools/opensta/report_libraries.py +28 -0
- siliconcompiler/tools/opensta/scripts/sc_procs.tcl +47 -0
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +74 -0
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +268 -0
- siliconcompiler/tools/opensta/timing.py +214 -0
- siliconcompiler/tools/slang/__init__.py +49 -0
- siliconcompiler/tools/slang/lint.py +101 -0
- siliconcompiler/tools/surelog/__init__.py +123 -0
- siliconcompiler/tools/surelog/parse.py +183 -0
- siliconcompiler/tools/surelog/templates/output.v +7 -0
- siliconcompiler/tools/sv2v/convert.py +46 -0
- siliconcompiler/tools/sv2v/sv2v.py +37 -0
- siliconcompiler/tools/template/template.py +125 -0
- siliconcompiler/tools/verilator/compile.py +139 -0
- siliconcompiler/tools/verilator/lint.py +19 -0
- siliconcompiler/tools/verilator/parse.py +27 -0
- siliconcompiler/tools/verilator/verilator.py +172 -0
- siliconcompiler/tools/vivado/__init__.py +7 -0
- siliconcompiler/tools/vivado/bitstream.py +21 -0
- siliconcompiler/tools/vivado/place.py +21 -0
- siliconcompiler/tools/vivado/route.py +21 -0
- siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +6 -0
- siliconcompiler/tools/vivado/scripts/sc_place.tcl +2 -0
- siliconcompiler/tools/vivado/scripts/sc_route.tcl +4 -0
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +45 -0
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +25 -0
- siliconcompiler/tools/vivado/syn_fpga.py +20 -0
- siliconcompiler/tools/vivado/vivado.py +147 -0
- siliconcompiler/tools/vpr/_json_constraint.py +63 -0
- siliconcompiler/tools/vpr/_xml_constraint.py +109 -0
- siliconcompiler/tools/vpr/place.py +137 -0
- siliconcompiler/tools/vpr/route.py +124 -0
- siliconcompiler/tools/vpr/screenshot.py +54 -0
- siliconcompiler/tools/vpr/show.py +88 -0
- siliconcompiler/tools/vpr/vpr.py +357 -0
- siliconcompiler/tools/xyce/xyce.py +36 -0
- siliconcompiler/tools/yosys/lec.py +56 -0
- siliconcompiler/tools/yosys/prepareLib.py +59 -0
- siliconcompiler/tools/yosys/sc_lec.tcl +84 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +79 -0
- siliconcompiler/tools/yosys/syn_asic.py +565 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +377 -0
- siliconcompiler/tools/yosys/syn_asic_fpga_shared.tcl +31 -0
- siliconcompiler/tools/yosys/syn_fpga.py +146 -0
- siliconcompiler/tools/yosys/syn_fpga.tcl +233 -0
- siliconcompiler/tools/yosys/syn_strategies.tcl +81 -0
- siliconcompiler/tools/yosys/techmaps/lcu_kogge_stone.v +39 -0
- siliconcompiler/tools/yosys/templates/abc.const +2 -0
- siliconcompiler/tools/yosys/yosys.py +147 -0
- siliconcompiler/units.py +259 -0
- siliconcompiler/use.py +177 -0
- siliconcompiler/utils/__init__.py +423 -0
- siliconcompiler/utils/asic.py +158 -0
- siliconcompiler/utils/showtools.py +25 -0
- siliconcompiler-0.26.5.dist-info/LICENSE +190 -0
- siliconcompiler-0.26.5.dist-info/METADATA +195 -0
- siliconcompiler-0.26.5.dist-info/RECORD +251 -0
- siliconcompiler-0.26.5.dist-info/WHEEL +5 -0
- siliconcompiler-0.26.5.dist-info/entry_points.txt +12 -0
- 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]
|