siliconcompiler 0.28.3__py3-none-any.whl → 0.28.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/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +88 -56
- siliconcompiler/apps/sc.py +33 -14
- siliconcompiler/apps/sc_dashboard.py +17 -10
- siliconcompiler/apps/sc_show.py +17 -15
- siliconcompiler/core.py +95 -55
- siliconcompiler/flows/drcflow.py +13 -0
- siliconcompiler/flows/interposerflow.py +17 -0
- siliconcompiler/fpgas/vpr_example.py +8 -0
- siliconcompiler/libs/interposer.py +8 -0
- siliconcompiler/package.py +3 -2
- siliconcompiler/pdks/interposer.py +8 -0
- siliconcompiler/remote/schema.py +11 -1
- siliconcompiler/remote/server.py +7 -2
- siliconcompiler/report/dashboard/__init__.py +9 -0
- siliconcompiler/report/dashboard/components/__init__.py +13 -1
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph.py +4 -3
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_node_tab.py +4 -1
- siliconcompiler/report/dashboard/layouts/vertical_flowgraph_sac_tabs.py +4 -1
- siliconcompiler/report/dashboard/state.py +3 -1
- siliconcompiler/report/summary_table.py +1 -2
- siliconcompiler/report/utils.py +1 -2
- siliconcompiler/scheduler/__init__.py +95 -0
- siliconcompiler/schema/schema_cfg.py +15 -3
- siliconcompiler/schema/schema_obj.py +51 -1
- siliconcompiler/sphinx_ext/dynamicgen.py +6 -0
- siliconcompiler/targets/interposer_demo.py +56 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +2 -0
- siliconcompiler/tools/_common/__init__.py +44 -6
- siliconcompiler/tools/_common/asic.py +79 -23
- siliconcompiler/tools/genfasm/genfasm.py +7 -0
- siliconcompiler/tools/ghdl/convert.py +7 -0
- siliconcompiler/tools/klayout/convert_drc_db.py +60 -0
- siliconcompiler/tools/klayout/drc.py +156 -0
- siliconcompiler/tools/klayout/export.py +9 -4
- siliconcompiler/tools/klayout/klayout.py +0 -1
- siliconcompiler/tools/klayout/klayout_convert_drc_db.py +182 -0
- siliconcompiler/tools/klayout/klayout_export.py +3 -0
- siliconcompiler/tools/klayout/klayout_utils.py +8 -2
- siliconcompiler/tools/klayout/operations.py +2 -0
- siliconcompiler/tools/klayout/screenshot.py +2 -0
- siliconcompiler/tools/klayout/show.py +4 -4
- siliconcompiler/tools/magic/drc.py +21 -0
- siliconcompiler/tools/magic/extspice.py +21 -0
- siliconcompiler/tools/magic/magic.py +29 -0
- siliconcompiler/tools/magic/sc_drc.tcl +2 -12
- siliconcompiler/tools/magic/sc_extspice.tcl +3 -15
- siliconcompiler/tools/openroad/metrics.py +45 -0
- siliconcompiler/tools/openroad/openroad.py +47 -2
- siliconcompiler/tools/openroad/rdlroute.py +97 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +16 -1
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +55 -9
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +0 -159
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +3 -1
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +184 -0
- siliconcompiler/tools/openroad/scripts/sc_report.tcl +170 -0
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +8 -2
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +0 -5
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +36 -6
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +11 -1
- siliconcompiler/tools/surelog/__init__.py +12 -0
- siliconcompiler/tools/verilator/compile.py +27 -0
- siliconcompiler/tools/verilator/verilator.py +9 -0
- siliconcompiler/tools/vpr/vpr.py +18 -0
- siliconcompiler/tools/xyce/__init__.py +1 -1
- siliconcompiler/tools/yosys/{syn_asic_fpga_shared.tcl → procs.tcl} +23 -0
- siliconcompiler/tools/yosys/sc_screenshot.tcl +104 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +7 -9
- siliconcompiler/tools/yosys/screenshot.py +153 -0
- siliconcompiler/tools/yosys/syn_asic.py +3 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +1 -3
- siliconcompiler/tools/yosys/syn_fpga.tcl +3 -2
- siliconcompiler/toolscripts/_tools.json +5 -6
- siliconcompiler/toolscripts/rhel8/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/rhel9/install-xyce.sh +4 -5
- siliconcompiler/toolscripts/ubuntu20/install-xyce.sh +5 -5
- siliconcompiler/toolscripts/ubuntu22/install-xyce.sh +2 -2
- siliconcompiler/toolscripts/ubuntu24/install-xyce.sh +2 -2
- siliconcompiler/utils/__init__.py +30 -1
- siliconcompiler/utils/showtools.py +4 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/METADATA +18 -5
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/RECORD +86 -72
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.28.3.dist-info → siliconcompiler-0.28.5.dist-info}/top_level.txt +0 -0
siliconcompiler/_metadata.py
CHANGED
siliconcompiler/apps/_common.py
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import glob
|
|
2
1
|
import os
|
|
3
2
|
|
|
4
3
|
|
|
4
|
+
# TODO: this is a hack to get around design name requirement: since legal
|
|
5
|
+
# design names probably can't contain spaces, we can detect if it is unset.
|
|
6
|
+
UNSET_DESIGN = ' unset '
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
def manifest_switches():
|
|
6
10
|
'''
|
|
7
11
|
Returns a list of manifest switches that can be used
|
|
@@ -14,63 +18,91 @@ def manifest_switches():
|
|
|
14
18
|
'-jobname']
|
|
15
19
|
|
|
16
20
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
if (src_file is not None) and (not chip.get('option', 'cfg')):
|
|
20
|
-
if not os.path.exists(src_file):
|
|
21
|
-
chip.logger.error(f'{src_file} cannot be found.')
|
|
22
|
-
return False
|
|
23
|
-
# only autoload manifest if user doesn't supply manually
|
|
24
|
-
manifest = _get_manifest(os.path.dirname(src_file))
|
|
25
|
-
if not manifest:
|
|
26
|
-
design = os.path.splitext(os.path.basename(src_file))[0]
|
|
27
|
-
chip.logger.error(f'Unable to automatically find manifest for design {design}. '
|
|
28
|
-
'Please provide a manifest explicitly using -cfg.')
|
|
29
|
-
return False
|
|
30
|
-
elif not chip.get('option', 'cfg'):
|
|
31
|
-
manifest = _get_manifest_from_design(chip)
|
|
32
|
-
if not manifest:
|
|
33
|
-
chip.logger.error(f'Could not find manifest for {chip.design}')
|
|
34
|
-
return False
|
|
21
|
+
def _get_manifests(cwd):
|
|
22
|
+
manifests = {}
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
24
|
+
def get_dirs(cwd):
|
|
25
|
+
dirs = []
|
|
26
|
+
for dirname in os.listdir(cwd):
|
|
27
|
+
fullpath = os.path.join(cwd, dirname)
|
|
28
|
+
if os.path.isdir(fullpath):
|
|
29
|
+
dirs.append((dirname, fullpath))
|
|
30
|
+
return dirs
|
|
31
|
+
|
|
32
|
+
for _, buildpath in get_dirs(cwd):
|
|
33
|
+
for design, designdir in get_dirs(buildpath):
|
|
34
|
+
for jobname, jobdir in get_dirs(designdir):
|
|
35
|
+
manifest = os.path.join(jobdir, f'{design}.pkg.json')
|
|
36
|
+
if os.path.isfile(manifest):
|
|
37
|
+
manifests[(design, jobname, None, None)] = manifest
|
|
38
|
+
for step, stepdir in get_dirs(jobdir):
|
|
39
|
+
for index, indexdir in get_dirs(stepdir):
|
|
40
|
+
manifest = os.path.join(indexdir, 'outputs', f'{design}.pkg.json')
|
|
41
|
+
if os.path.isfile(manifest):
|
|
42
|
+
manifests[(design, jobname, step, index)] = manifest
|
|
43
|
+
else:
|
|
44
|
+
manifest = os.path.join(indexdir, 'inputs', f'{design}.pkg.json')
|
|
45
|
+
if os.path.isfile(manifest):
|
|
46
|
+
manifests[(design, jobname, step, index)] = manifest
|
|
47
|
+
|
|
48
|
+
organized_manifest = {}
|
|
49
|
+
for (design, job, step, index), manifest in manifests.items():
|
|
50
|
+
jobs = organized_manifest.setdefault(design, {})
|
|
51
|
+
jobs.setdefault(job, {})[step, index] = os.path.abspath(manifest)
|
|
52
|
+
|
|
53
|
+
return organized_manifest
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def pick_manifest_from_file(chip, src_file, all_manifests):
|
|
57
|
+
if src_file is None:
|
|
54
58
|
return None
|
|
55
|
-
return manifest
|
|
56
59
|
|
|
60
|
+
if not os.path.exists(src_file):
|
|
61
|
+
chip.logger.error(f'{src_file} cannot be found.')
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
src_dir = os.path.abspath(os.path.dirname(src_file))
|
|
65
|
+
for _, jobs in all_manifests.items():
|
|
66
|
+
for _, nodes in jobs.items():
|
|
67
|
+
for manifest in nodes.values():
|
|
68
|
+
if src_dir == os.path.dirname(manifest):
|
|
69
|
+
return manifest
|
|
57
70
|
|
|
58
|
-
def _get_manifest_from_design(chip):
|
|
59
|
-
for jobname, step, index in [
|
|
60
|
-
(chip.get('option', 'jobname'),
|
|
61
|
-
chip.get('arg', 'step'),
|
|
62
|
-
chip.get('arg', 'index')),
|
|
63
|
-
(chip.get('option', 'jobname'),
|
|
64
|
-
None,
|
|
65
|
-
None),
|
|
66
|
-
(chip.schema.get_default('option', 'jobname'),
|
|
67
|
-
chip.get('arg', 'step'),
|
|
68
|
-
chip.get('arg', 'index')),
|
|
69
|
-
(chip.schema.get_default('option', 'jobname'),
|
|
70
|
-
None,
|
|
71
|
-
None)]:
|
|
72
|
-
manifest = _get_manifest(chip.getworkdir(jobname=jobname, step=step, index=index))
|
|
73
|
-
|
|
74
|
-
if manifest:
|
|
75
|
-
return manifest
|
|
76
71
|
return None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def pick_manifest(chip, src_file=None):
|
|
75
|
+
all_manifests = _get_manifests(os.getcwd())
|
|
76
|
+
|
|
77
|
+
manifest = pick_manifest_from_file(chip, src_file, all_manifests)
|
|
78
|
+
if manifest:
|
|
79
|
+
return manifest
|
|
80
|
+
|
|
81
|
+
if chip.design == UNSET_DESIGN:
|
|
82
|
+
if len(all_manifests) == 1:
|
|
83
|
+
chip.set('design', list(all_manifests.keys())[0])
|
|
84
|
+
else:
|
|
85
|
+
chip.logger.error('Design name is not set')
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
if chip.design not in all_manifests:
|
|
89
|
+
chip.logger.error(f'Could not find manifest for {chip.design}')
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
if chip.get('option', 'jobname') not in all_manifests[chip.design] and \
|
|
93
|
+
len(all_manifests[chip.design]) != 1:
|
|
94
|
+
chip.logger.error(f'Could not determine jobname for {chip.design}')
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
jobname = chip.get('option', 'jobname')
|
|
98
|
+
if chip.get('option', 'jobname') not in all_manifests[chip.design]:
|
|
99
|
+
jobname = list(all_manifests[chip.design].keys())[0]
|
|
100
|
+
|
|
101
|
+
if (None, None) in all_manifests[chip.design][jobname]:
|
|
102
|
+
manifest = all_manifests[chip.design][jobname][None, None]
|
|
103
|
+
else:
|
|
104
|
+
# pick newest manifest
|
|
105
|
+
manifest = list(sorted(all_manifests[chip.design][jobname].values(),
|
|
106
|
+
key=lambda file: os.stat(file).st_ctime))[-1]
|
|
107
|
+
|
|
108
|
+
return manifest
|
siliconcompiler/apps/sc.py
CHANGED
|
@@ -10,6 +10,37 @@ from siliconcompiler.targets import skywater130_demo
|
|
|
10
10
|
from siliconcompiler import SiliconCompilerError
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def _infer_designname(chip):
|
|
14
|
+
topfile = None
|
|
15
|
+
sourcesets = chip.getkeys('input')
|
|
16
|
+
for sourceset in reversed(('rtl', 'hll')):
|
|
17
|
+
if sourceset in sourcesets:
|
|
18
|
+
sourcesets.remove(sourceset)
|
|
19
|
+
sourcesets.insert(0, sourceset)
|
|
20
|
+
for sourceset in sourcesets:
|
|
21
|
+
for filetype in chip.getkeys('input', sourceset):
|
|
22
|
+
all_vals = chip.schema._getvals('input', sourceset, filetype)
|
|
23
|
+
if all_vals:
|
|
24
|
+
# just look at first value
|
|
25
|
+
sources, _, _ = all_vals[0]
|
|
26
|
+
# grab first source
|
|
27
|
+
topfile = sources[0]
|
|
28
|
+
break
|
|
29
|
+
if topfile:
|
|
30
|
+
break
|
|
31
|
+
|
|
32
|
+
if not topfile:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
root = os.path.basename(topfile)
|
|
36
|
+
while True:
|
|
37
|
+
root, ext = os.path.splitext(root)
|
|
38
|
+
if not ext:
|
|
39
|
+
break
|
|
40
|
+
|
|
41
|
+
return root
|
|
42
|
+
|
|
43
|
+
|
|
13
44
|
###########################
|
|
14
45
|
def main():
|
|
15
46
|
progname = "sc"
|
|
@@ -50,24 +81,12 @@ def main():
|
|
|
50
81
|
|
|
51
82
|
# Set design if none specified
|
|
52
83
|
if chip.get('design') == UNSET_DESIGN:
|
|
53
|
-
|
|
54
|
-
for sourceset in ('rtl', 'hll'):
|
|
55
|
-
for filetype in chip.getkeys('input', sourceset):
|
|
56
|
-
all_vals = chip.schema._getvals('input', sourceset, filetype)
|
|
57
|
-
if all_vals:
|
|
58
|
-
# just look at first value
|
|
59
|
-
sources, _, _ = all_vals[0]
|
|
60
|
-
# grab first source
|
|
61
|
-
topfile = sources[0]
|
|
62
|
-
break
|
|
63
|
-
if topfile:
|
|
64
|
-
break
|
|
84
|
+
topmodule = _infer_designname(chip)
|
|
65
85
|
|
|
66
|
-
if not
|
|
86
|
+
if not topmodule:
|
|
67
87
|
chip.logger.error('Invalid arguments: either specify -design or provide sources.')
|
|
68
88
|
return 1
|
|
69
89
|
|
|
70
|
-
topmodule = os.path.splitext(os.path.basename(topfile))[0]
|
|
71
90
|
chip.set('design', topmodule)
|
|
72
91
|
|
|
73
92
|
# Set demo target if none specified
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import sys
|
|
3
3
|
import siliconcompiler
|
|
4
4
|
import os
|
|
5
|
-
from siliconcompiler.apps._common import
|
|
5
|
+
from siliconcompiler.apps._common import pick_manifest, manifest_switches, UNSET_DESIGN
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def main():
|
|
@@ -11,9 +11,16 @@ def main():
|
|
|
11
11
|
-----------------------------------------------------------
|
|
12
12
|
SC app to open a dashboard for a given manifest.
|
|
13
13
|
|
|
14
|
-
To open:
|
|
14
|
+
To open and allow sc-dashboard to autoload manifest:
|
|
15
|
+
sc-dashboard
|
|
16
|
+
|
|
17
|
+
To open by specifying manifest:
|
|
15
18
|
sc-dashboard -cfg <path to manifest>
|
|
16
19
|
|
|
20
|
+
To open by specifying design and optionally jobname:
|
|
21
|
+
sc-dashboard -design <name>
|
|
22
|
+
sc-dashboard -design <name> -jobname <jobname>
|
|
23
|
+
|
|
17
24
|
To specify a different port than the default:
|
|
18
25
|
sc-dashboard -cfg <path to manifest> -port 10000
|
|
19
26
|
|
|
@@ -23,10 +30,6 @@ To include another chip object to compare to:
|
|
|
23
30
|
-----------------------------------------------------------
|
|
24
31
|
"""
|
|
25
32
|
|
|
26
|
-
# TODO: this is a hack to get around design name requirement: since legal
|
|
27
|
-
# design names probably can't contain spaces, we can detect if it is unset.
|
|
28
|
-
UNSET_DESIGN = ' unset '
|
|
29
|
-
|
|
30
33
|
# Create a base chip class.
|
|
31
34
|
chip = siliconcompiler.Chip(UNSET_DESIGN)
|
|
32
35
|
|
|
@@ -54,15 +57,19 @@ To include another chip object to compare to:
|
|
|
54
57
|
chip.logger.error(e)
|
|
55
58
|
return 1
|
|
56
59
|
|
|
60
|
+
if not chip.get('option', 'cfg'):
|
|
61
|
+
manifest = pick_manifest(chip)
|
|
62
|
+
|
|
63
|
+
if manifest:
|
|
64
|
+
chip.logger.info(f'Loading manifest: {manifest}')
|
|
65
|
+
chip.read_manifest(manifest)
|
|
66
|
+
|
|
57
67
|
# Error checking
|
|
58
68
|
design = chip.get('design')
|
|
59
69
|
if design == UNSET_DESIGN:
|
|
60
70
|
chip.logger.error('Design not loaded')
|
|
61
71
|
return 1
|
|
62
72
|
|
|
63
|
-
if not load_manifest(chip, None):
|
|
64
|
-
return 1
|
|
65
|
-
|
|
66
73
|
graph_chips = []
|
|
67
74
|
if switches['graph_cfg']:
|
|
68
75
|
for i, name_and_file_path in enumerate(switches['graph_cfg']):
|
|
@@ -88,7 +95,7 @@ To include another chip object to compare to:
|
|
|
88
95
|
'cfg_path': os.path.abspath(file_path)
|
|
89
96
|
})
|
|
90
97
|
|
|
91
|
-
chip.
|
|
98
|
+
chip.dashboard(wait=True, port=switches['port'], graph_chips=graph_chips)
|
|
92
99
|
|
|
93
100
|
return 0
|
|
94
101
|
|
siliconcompiler/apps/sc_show.py
CHANGED
|
@@ -3,7 +3,7 @@ import sys
|
|
|
3
3
|
import os
|
|
4
4
|
import siliconcompiler
|
|
5
5
|
from siliconcompiler.utils import get_default_iomap
|
|
6
|
-
from siliconcompiler.apps._common import
|
|
6
|
+
from siliconcompiler.apps._common import manifest_switches, pick_manifest, UNSET_DESIGN
|
|
7
7
|
from siliconcompiler.utils import get_file_ext
|
|
8
8
|
|
|
9
9
|
|
|
@@ -18,6 +18,9 @@ def main():
|
|
|
18
18
|
|
|
19
19
|
Examples:
|
|
20
20
|
|
|
21
|
+
sc-show
|
|
22
|
+
(displays build/adder/job0/write_gds/0/outputs/adder.gds)
|
|
23
|
+
|
|
21
24
|
sc-show -design adder
|
|
22
25
|
(displays build/adder/job0/write_gds/0/outputs/adder.gds)
|
|
23
26
|
|
|
@@ -40,10 +43,6 @@ def main():
|
|
|
40
43
|
(displays build/adder/job0/route/1/outputs/adder.def)
|
|
41
44
|
"""
|
|
42
45
|
|
|
43
|
-
# TODO: this is a hack to get around design name requirement: since legal
|
|
44
|
-
# design names probably can't contain spaces, we can detect if it is unset.
|
|
45
|
-
UNSET_DESIGN = ' unset '
|
|
46
|
-
|
|
47
46
|
# Create a base chip class.
|
|
48
47
|
chip = siliconcompiler.Chip(UNSET_DESIGN)
|
|
49
48
|
|
|
@@ -81,10 +80,6 @@ def main():
|
|
|
81
80
|
chip.logger.error(e)
|
|
82
81
|
return 1
|
|
83
82
|
|
|
84
|
-
# Error checking
|
|
85
|
-
design = chip.get('design')
|
|
86
|
-
design_set = design != UNSET_DESIGN
|
|
87
|
-
|
|
88
83
|
# Search input keys for files
|
|
89
84
|
input_mode = []
|
|
90
85
|
for fileset in chip.getkeys('input'):
|
|
@@ -92,11 +87,6 @@ def main():
|
|
|
92
87
|
if chip.schema._getvals('input', fileset, mode):
|
|
93
88
|
input_mode = [('input', fileset, mode)]
|
|
94
89
|
|
|
95
|
-
if not (design_set or input_mode):
|
|
96
|
-
chip.logger.error('Nothing to load: please define a target with '
|
|
97
|
-
'-cfg, -design, and/or inputs.')
|
|
98
|
-
return 1
|
|
99
|
-
|
|
100
90
|
filename = None
|
|
101
91
|
if input_mode:
|
|
102
92
|
check_ext = list(chip._showtools.keys())
|
|
@@ -115,7 +105,19 @@ def main():
|
|
|
115
105
|
|
|
116
106
|
filename = get_file_from_keys()
|
|
117
107
|
|
|
118
|
-
|
|
108
|
+
# Attempt to load a manifest
|
|
109
|
+
if not chip.get('option', 'cfg'):
|
|
110
|
+
manifest = pick_manifest(chip, src_file=filename)
|
|
111
|
+
if manifest:
|
|
112
|
+
chip.logger.info(f'Loading manifest: {manifest}')
|
|
113
|
+
chip.read_manifest(manifest)
|
|
114
|
+
|
|
115
|
+
# Error checking
|
|
116
|
+
design = chip.get('design')
|
|
117
|
+
design_set = design != UNSET_DESIGN
|
|
118
|
+
if not (design_set or input_mode):
|
|
119
|
+
chip.logger.error('Nothing to load: please define a target with '
|
|
120
|
+
'-cfg, -design, and/or inputs.')
|
|
119
121
|
return 1
|
|
120
122
|
|
|
121
123
|
# Read in file
|
siliconcompiler/core.py
CHANGED
|
@@ -1363,7 +1363,7 @@ class Chip:
|
|
|
1363
1363
|
basename = str(pathlib.PurePosixPath(*path_paths[0:n]))
|
|
1364
1364
|
endname = str(pathlib.PurePosixPath(*path_paths[n:]))
|
|
1365
1365
|
|
|
1366
|
-
import_name =
|
|
1366
|
+
import_name = utils.get_hashed_filename(basename, package=package)
|
|
1367
1367
|
if import_name not in collected_files:
|
|
1368
1368
|
continue
|
|
1369
1369
|
|
|
@@ -2051,6 +2051,30 @@ class Chip:
|
|
|
2051
2051
|
dot.graph_attr['ranksep'] = '0.75'
|
|
2052
2052
|
dot.attr(bgcolor=background)
|
|
2053
2053
|
|
|
2054
|
+
subgraphs = {
|
|
2055
|
+
"graphs": {
|
|
2056
|
+
"sc-inputs": {
|
|
2057
|
+
"graphs": {},
|
|
2058
|
+
"nodes": []
|
|
2059
|
+
}
|
|
2060
|
+
},
|
|
2061
|
+
"nodes": []
|
|
2062
|
+
}
|
|
2063
|
+
for node, info in nodes.items():
|
|
2064
|
+
if info['is_input']:
|
|
2065
|
+
subgraph_temp = subgraphs["graphs"]["sc-inputs"]
|
|
2066
|
+
else:
|
|
2067
|
+
subgraph_temp = subgraphs
|
|
2068
|
+
|
|
2069
|
+
for key in node.split(".")[0:-1]:
|
|
2070
|
+
if key not in subgraph_temp["graphs"]:
|
|
2071
|
+
subgraph_temp["graphs"][key] = {
|
|
2072
|
+
"graphs": {},
|
|
2073
|
+
"nodes": []
|
|
2074
|
+
}
|
|
2075
|
+
subgraph_temp = subgraph_temp["graphs"][key]
|
|
2076
|
+
subgraph_temp["nodes"].append(node)
|
|
2077
|
+
|
|
2054
2078
|
with dot.subgraph(name='inputs') as input_graph:
|
|
2055
2079
|
input_graph.graph_attr['cluster'] = 'true'
|
|
2056
2080
|
input_graph.graph_attr['color'] = background
|
|
@@ -2062,34 +2086,74 @@ class Chip:
|
|
|
2062
2086
|
fontcolor=fontcolor, fontsize=fontsize, ordering="in",
|
|
2063
2087
|
penwidth=penwidth, fillcolor=fillcolor, shape="box")
|
|
2064
2088
|
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
input_graph_nodes.graph_attr['color'] = background
|
|
2089
|
+
def make_node(graph, node, prefix):
|
|
2090
|
+
info = nodes[node]
|
|
2068
2091
|
|
|
2069
|
-
# add nodes
|
|
2070
2092
|
shape = "oval" if not show_io else "Mrecord"
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2093
|
+
task_label = f"\\n ({info['task']})" if info['task'] is not None else ""
|
|
2094
|
+
if show_io:
|
|
2095
|
+
input_labels = [f"<{ikey}> {ifile}" for ifile, ikey in info['inputs'].items()]
|
|
2096
|
+
output_labels = [f"<{okey}> {ofile}" for ofile, okey in info['outputs'].items()]
|
|
2097
|
+
center_text = f"\\n {node.replace(prefix, '')} {task_label} \\n\\n"
|
|
2098
|
+
labelname = "{"
|
|
2099
|
+
if input_labels:
|
|
2100
|
+
labelname += f"{{ {' | '.join(input_labels)} }} |"
|
|
2101
|
+
labelname += center_text
|
|
2102
|
+
if output_labels:
|
|
2103
|
+
labelname += f"| {{ {' | '.join(output_labels)} }}"
|
|
2104
|
+
labelname += "}"
|
|
2105
|
+
else:
|
|
2106
|
+
labelname = f"{node.replace(prefix, '')}{task_label}"
|
|
2107
|
+
|
|
2108
|
+
graph.node(node, label=labelname, bordercolor=fontcolor, style='filled',
|
|
2109
|
+
fontcolor=fontcolor, fontsize=fontsize, ordering="in",
|
|
2110
|
+
penwidth=penwidth, fillcolor=fillcolor, shape=shape)
|
|
2111
|
+
|
|
2112
|
+
graph_idx = 0
|
|
2113
|
+
|
|
2114
|
+
def get_node_count(graph_info):
|
|
2115
|
+
nodes = len(graph_info["nodes"])
|
|
2116
|
+
|
|
2117
|
+
for subgraph in graph_info["graphs"]:
|
|
2118
|
+
nodes += get_node_count(graph_info["graphs"][subgraph])
|
|
2119
|
+
|
|
2120
|
+
return nodes
|
|
2121
|
+
|
|
2122
|
+
def build_graph(graph_info, parent, prefix):
|
|
2123
|
+
nonlocal graph_idx
|
|
2124
|
+
|
|
2125
|
+
for subgraph in graph_info["graphs"]:
|
|
2126
|
+
child_prefix = prefix
|
|
2127
|
+
if get_node_count(graph_info["graphs"][subgraph]) > 1:
|
|
2128
|
+
child_prefix = f"{child_prefix}{subgraph}."
|
|
2129
|
+
graph = graphviz.Digraph(name=f"cluster_{graph_idx}")
|
|
2130
|
+
graph_idx += 1
|
|
2131
|
+
|
|
2132
|
+
graph.graph_attr['rankdir'] = rankdir
|
|
2133
|
+
graph.attr(bgcolor=background)
|
|
2134
|
+
|
|
2135
|
+
if subgraph == "sc-inputs":
|
|
2136
|
+
graph.attr(style='invis')
|
|
2137
|
+
else:
|
|
2138
|
+
graph.attr(color=fontcolor)
|
|
2139
|
+
graph.attr(style='rounded')
|
|
2140
|
+
graph.attr(shape='oval')
|
|
2141
|
+
graph.attr(label=subgraph)
|
|
2142
|
+
graph.attr(labeljust='l')
|
|
2143
|
+
graph.attr(fontcolor=fontcolor)
|
|
2144
|
+
graph.attr(fontsize=str(int(fontsize) + 2))
|
|
2084
2145
|
else:
|
|
2085
|
-
|
|
2146
|
+
graph = parent
|
|
2147
|
+
|
|
2148
|
+
build_graph(graph_info["graphs"][subgraph], graph, child_prefix)
|
|
2149
|
+
|
|
2150
|
+
if graph is not parent:
|
|
2151
|
+
parent.subgraph(graph)
|
|
2086
2152
|
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
fontcolor=fontcolor, fontsize=fontsize, ordering="in",
|
|
2092
|
-
penwidth=penwidth, fillcolor=fillcolor, shape=shape)
|
|
2153
|
+
for subnode in graph_info["nodes"]:
|
|
2154
|
+
make_node(parent, subnode, prefix)
|
|
2155
|
+
|
|
2156
|
+
build_graph(subgraphs, dot, "")
|
|
2093
2157
|
|
|
2094
2158
|
for edge0, edge1, weight in edges:
|
|
2095
2159
|
dot.edge(f'{edge0}{out_label_suffix}', f'{edge1}{in_label_suffix}', weight=str(weight))
|
|
@@ -2394,7 +2458,7 @@ class Chip:
|
|
|
2394
2458
|
|
|
2395
2459
|
abspath = dirs[(package, path)]
|
|
2396
2460
|
if abspath:
|
|
2397
|
-
filename =
|
|
2461
|
+
filename = utils.get_hashed_filename(posix_path, package=package)
|
|
2398
2462
|
dst_path = os.path.join(directory, filename)
|
|
2399
2463
|
if os.path.exists(dst_path):
|
|
2400
2464
|
continue
|
|
@@ -2466,7 +2530,7 @@ class Chip:
|
|
|
2466
2530
|
|
|
2467
2531
|
abspath = files[(package, path)]
|
|
2468
2532
|
if abspath:
|
|
2469
|
-
filename =
|
|
2533
|
+
filename = utils.get_hashed_filename(posix_path, package=package)
|
|
2470
2534
|
dst_path = os.path.join(directory, filename)
|
|
2471
2535
|
if verbose:
|
|
2472
2536
|
self.logger.info(f"Copying {abspath} to '{directory}' directory")
|
|
@@ -2702,12 +2766,12 @@ class Chip:
|
|
|
2702
2766
|
return hashlist
|
|
2703
2767
|
|
|
2704
2768
|
###########################################################################
|
|
2705
|
-
def
|
|
2769
|
+
def dashboard(self, wait=True, port=None, graph_chips=None):
|
|
2706
2770
|
'''
|
|
2707
2771
|
Open a session of the dashboard.
|
|
2708
2772
|
|
|
2709
2773
|
The dashboard can be viewed in any webbrowser and can be accessed via:
|
|
2710
|
-
http://localhost
|
|
2774
|
+
http://localhost:<port>/
|
|
2711
2775
|
|
|
2712
2776
|
Args:
|
|
2713
2777
|
wait (bool): If True, this call will wait in this method
|
|
@@ -2718,7 +2782,7 @@ class Chip:
|
|
|
2718
2782
|
{'chip': chip object, 'name': chip name}
|
|
2719
2783
|
|
|
2720
2784
|
Examples:
|
|
2721
|
-
>>> chip.
|
|
2785
|
+
>>> chip.dashboard()
|
|
2722
2786
|
Opens a sesison of the dashboard.
|
|
2723
2787
|
'''
|
|
2724
2788
|
if self._dash:
|
|
@@ -3143,6 +3207,7 @@ class Chip:
|
|
|
3143
3207
|
self.set('option', 'nodisplay', False, clobber=True)
|
|
3144
3208
|
self.set('option', 'continue', True, clobber=True)
|
|
3145
3209
|
self.set('option', 'quiet', False, clobber=True)
|
|
3210
|
+
self.set('option', 'clean', True, clobber=True)
|
|
3146
3211
|
self.set('arg', 'step', None, clobber=True)
|
|
3147
3212
|
self.set('arg', 'index', None, clobber=True)
|
|
3148
3213
|
self.unset('option', 'to')
|
|
@@ -3237,31 +3302,6 @@ class Chip:
|
|
|
3237
3302
|
|
|
3238
3303
|
return os.path.join(*dirlist)
|
|
3239
3304
|
|
|
3240
|
-
#######################################
|
|
3241
|
-
def __get_imported_filename(self, pathstr, package=None):
|
|
3242
|
-
''' Utility to map collected file to an unambiguous name based on its path.
|
|
3243
|
-
|
|
3244
|
-
The mapping looks like:
|
|
3245
|
-
path/to/file.ext => file_<md5('path/to/file.ext')>.ext
|
|
3246
|
-
'''
|
|
3247
|
-
path = pathlib.PurePosixPath(pathstr)
|
|
3248
|
-
ext = ''.join(path.suffixes)
|
|
3249
|
-
|
|
3250
|
-
# strip off all file suffixes to get just the bare name
|
|
3251
|
-
barepath = path
|
|
3252
|
-
while barepath.suffix:
|
|
3253
|
-
barepath = pathlib.PurePosixPath(barepath.stem)
|
|
3254
|
-
filename = str(barepath.parts[-1])
|
|
3255
|
-
|
|
3256
|
-
if not package:
|
|
3257
|
-
package = ''
|
|
3258
|
-
else:
|
|
3259
|
-
package = f'{package}:'
|
|
3260
|
-
path_to_hash = f'{package}{str(path)}'
|
|
3261
|
-
pathhash = hashlib.sha1(path_to_hash.encode('utf-8')).hexdigest()
|
|
3262
|
-
|
|
3263
|
-
return f'{filename}_{pathhash}{ext}'
|
|
3264
|
-
|
|
3265
3305
|
def error(self, msg):
|
|
3266
3306
|
'''
|
|
3267
3307
|
Raises error.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from siliconcompiler import Flow
|
|
2
|
+
|
|
3
|
+
from siliconcompiler.tools.openroad import rdlroute
|
|
4
|
+
from siliconcompiler.tools.klayout import export
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def setup():
|
|
8
|
+
'''
|
|
9
|
+
A flow to perform RDL routing and generate a GDS
|
|
10
|
+
'''
|
|
11
|
+
flow = Flow('interposerflow')
|
|
12
|
+
flow.node('interposerflow', 'rdlroute', rdlroute)
|
|
13
|
+
flow.node('interposerflow', 'write_gds', export)
|
|
14
|
+
|
|
15
|
+
flow.edge('interposerflow', 'rdlroute', 'write_gds')
|
|
16
|
+
|
|
17
|
+
return flow
|
|
@@ -43,6 +43,14 @@ def setup():
|
|
|
43
43
|
|
|
44
44
|
fpga.set('fpga', part_name, 'vendor', vendor)
|
|
45
45
|
|
|
46
|
+
# Part name is specified per architecture file. Device code specifies
|
|
47
|
+
# which <fixed_layout> name to use when running VPR. These examples
|
|
48
|
+
# use the following names:
|
|
49
|
+
if (part_name == 'example_arch_X005Y005'):
|
|
50
|
+
fpga.set('fpga', part_name, 'var', 'vpr_device_code', 'fpga_beta')
|
|
51
|
+
else:
|
|
52
|
+
fpga.set('fpga', part_name, 'var', 'vpr_device_code', part_name)
|
|
53
|
+
|
|
46
54
|
fpga.set('fpga', part_name, 'lutsize', lut_size)
|
|
47
55
|
|
|
48
56
|
arch_root = os.path.join(flow_root, 'arch', part_name)
|
siliconcompiler/package.py
CHANGED
|
@@ -88,7 +88,8 @@ def _path(chip, package, download_handler):
|
|
|
88
88
|
chip._packages[package] = data_path
|
|
89
89
|
return data_path
|
|
90
90
|
|
|
91
|
-
raise SiliconCompilerError(f'Extracting {package} data to {data_path} failed'
|
|
91
|
+
raise SiliconCompilerError(f'Extracting {package} data to {data_path} failed',
|
|
92
|
+
chip=chip)
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
def path(chip, package):
|
|
@@ -188,7 +189,7 @@ def clone_synchronized(chip, package, data, data_path):
|
|
|
188
189
|
elif url.scheme in ['git', 'git+https']:
|
|
189
190
|
chip.logger.error('Failed to authenticate. Please use a token or ssh.')
|
|
190
191
|
else:
|
|
191
|
-
|
|
192
|
+
chip.logger.error(str(e))
|
|
192
193
|
|
|
193
194
|
|
|
194
195
|
def clone_from_git(chip, package, data, repo_path):
|