siliconcompiler 0.29.3__py3-none-any.whl → 0.30.0__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/sc.py +1 -1
- siliconcompiler/apps/sc_install.py +46 -3
- siliconcompiler/core.py +15 -4
- siliconcompiler/remote/client.py +3 -0
- siliconcompiler/scheduler/__init__.py +9 -3
- siliconcompiler/schema/schema_cfg.py +149 -92
- siliconcompiler/tools/__init__.py +4 -2
- siliconcompiler/tools/_common/asic.py +3 -0
- siliconcompiler/tools/_common/asic_clock.py +101 -0
- siliconcompiler/tools/bambu/__init__.py +32 -0
- siliconcompiler/tools/bambu/convert.py +93 -12
- siliconcompiler/tools/bluespec/__init__.py +35 -0
- siliconcompiler/tools/bluespec/convert.py +44 -5
- siliconcompiler/tools/graphviz/__init__.py +12 -0
- siliconcompiler/tools/graphviz/screenshot.py +48 -0
- siliconcompiler/tools/graphviz/show.py +20 -0
- siliconcompiler/tools/openroad/_apr.py +17 -0
- siliconcompiler/tools/openroad/fillmetal_insertion.py +0 -1
- siliconcompiler/tools/openroad/init_floorplan.py +7 -1
- siliconcompiler/tools/openroad/macro_placement.py +10 -2
- siliconcompiler/tools/openroad/pin_placement.py +0 -1
- siliconcompiler/tools/openroad/power_grid.py +6 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +15 -5
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +9 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +54 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +24 -0
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +28 -6
- siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +10 -16
- siliconcompiler/tools/slang/__init__.py +1 -0
- siliconcompiler/tools/verilator/verilator.py +1 -0
- siliconcompiler/tools/yosys/__init__.py +26 -23
- siliconcompiler/tools/yosys/procs.tcl +17 -0
- siliconcompiler/tools/yosys/syn_asic.py +12 -65
- siliconcompiler/tools/yosys/syn_asic.tcl +6 -51
- siliconcompiler/toolscripts/_tools.json +5 -5
- siliconcompiler/toolscripts/rhel8/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/rhel9/install-openroad.sh +34 -0
- siliconcompiler/toolscripts/rhel9/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +1 -1
- siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +1 -1
- siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +1 -1
- siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +1 -1
- siliconcompiler/utils/__init__.py +13 -0
- siliconcompiler/utils/showtools.py +7 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/METADATA +9 -9
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/RECORD +58 -55
- siliconcompiler/tools/bambu/bambu.py +0 -32
- siliconcompiler/tools/bluespec/bluespec.py +0 -40
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.30.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from siliconcompiler.utils import sc_open
|
|
3
|
+
from siliconcompiler.tools._common.asic import get_tool_task
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def __get_clock_data(chip, clock_units_multiplier=1):
|
|
7
|
+
step = chip.get('arg', 'step')
|
|
8
|
+
index = chip.get('arg', 'index')
|
|
9
|
+
|
|
10
|
+
period = None
|
|
11
|
+
# get clock information from sdc files
|
|
12
|
+
if chip.valid('input', 'constraint', 'sdc'):
|
|
13
|
+
for sdc in chip.find_files('input', 'constraint', 'sdc', step=step, index=index):
|
|
14
|
+
lines = []
|
|
15
|
+
with sc_open(sdc) as f:
|
|
16
|
+
lines = f.read().splitlines()
|
|
17
|
+
|
|
18
|
+
# collect simple variables in case clock is specified with a variable
|
|
19
|
+
re_var = r"[A-Za-z0-9_]+"
|
|
20
|
+
re_num = r"[0-9\.]+"
|
|
21
|
+
sdc_vars = {}
|
|
22
|
+
for line in lines:
|
|
23
|
+
tcl_variable = re.findall(fr"^\s*set\s+({re_var})\s+({re_num}|\${re_var})", line)
|
|
24
|
+
if tcl_variable:
|
|
25
|
+
var_name, var_value = tcl_variable[0]
|
|
26
|
+
sdc_vars[f'${var_name}'] = var_value
|
|
27
|
+
|
|
28
|
+
# TODO: handle line continuations
|
|
29
|
+
for line in lines:
|
|
30
|
+
clock_period = re.findall(fr"create_clock\s.*-period\s+({re_num}|\${re_var})",
|
|
31
|
+
line)
|
|
32
|
+
if clock_period:
|
|
33
|
+
convert_period = clock_period[0]
|
|
34
|
+
while isinstance(convert_period, str) and convert_period[0] == "$":
|
|
35
|
+
if convert_period in sdc_vars:
|
|
36
|
+
convert_period = sdc_vars[convert_period]
|
|
37
|
+
else:
|
|
38
|
+
break
|
|
39
|
+
if isinstance(convert_period, str) and convert_period[0] == "$":
|
|
40
|
+
chip.logger.warning('Unable to identify clock period from '
|
|
41
|
+
f'{clock_period[0]}.')
|
|
42
|
+
continue
|
|
43
|
+
else:
|
|
44
|
+
try:
|
|
45
|
+
clock_period = float(convert_period)
|
|
46
|
+
except TypeError:
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
clock_period = clock_period * clock_units_multiplier
|
|
50
|
+
|
|
51
|
+
if period is None:
|
|
52
|
+
period = clock_period
|
|
53
|
+
else:
|
|
54
|
+
period = min(period, clock_period)
|
|
55
|
+
|
|
56
|
+
if period is not None:
|
|
57
|
+
return period, None, [('input', 'constraint', 'sdc')]
|
|
58
|
+
|
|
59
|
+
if period is None:
|
|
60
|
+
keys = []
|
|
61
|
+
key_pin = None
|
|
62
|
+
# get clock information from defined clocks
|
|
63
|
+
for pin in chip.getkeys('datasheet', 'pin'):
|
|
64
|
+
for mode in chip.getkeys('datasheet', 'pin', pin, 'type'):
|
|
65
|
+
if chip.get('datasheet', 'pin', pin, 'type', mode) == 'clock':
|
|
66
|
+
clock_period = min(chip.get('datasheet', 'pin', pin, 'tperiod', mode)) * 1e9
|
|
67
|
+
|
|
68
|
+
if period is None:
|
|
69
|
+
period = clock_period
|
|
70
|
+
keys = [
|
|
71
|
+
('datasheet', 'pin', pin, 'type', mode),
|
|
72
|
+
('datasheet', 'pin', pin, 'tperiod', mode)
|
|
73
|
+
]
|
|
74
|
+
key_pin = pin
|
|
75
|
+
else:
|
|
76
|
+
if clock_period < period:
|
|
77
|
+
period = clock_period
|
|
78
|
+
keys = [
|
|
79
|
+
('datasheet', 'pin', pin, 'type', mode),
|
|
80
|
+
('datasheet', 'pin', pin, 'tperiod', mode)
|
|
81
|
+
]
|
|
82
|
+
key_pin = pin
|
|
83
|
+
return period, key_pin, keys
|
|
84
|
+
|
|
85
|
+
return None, None, []
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def add_clock_requirements(chip):
|
|
89
|
+
_, _, keys = __get_clock_data(chip)
|
|
90
|
+
|
|
91
|
+
step = chip.get('arg', 'step')
|
|
92
|
+
index = chip.get('arg', 'index')
|
|
93
|
+
tool, task = get_tool_task(chip, step, index)
|
|
94
|
+
for key in keys:
|
|
95
|
+
chip.add('tool', tool, 'task', task, 'require', ','.join(key),
|
|
96
|
+
step=step, index=index)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_clock_period(chip, clock_units_multiplier=1):
|
|
100
|
+
period, name, _ = __get_clock_data(chip, clock_units_multiplier=clock_units_multiplier)
|
|
101
|
+
return name, period
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'''
|
|
2
|
+
The primary objective of the PandA project is to develop a usable framework that will
|
|
3
|
+
enable the research of new ideas in the HW-SW Co-Design field.
|
|
4
|
+
|
|
5
|
+
The PandA framework includes methodologies supporting the research on high-level synthesis
|
|
6
|
+
of hardware accelerators, on parallelism extraction for embedded systems, on hardware/software
|
|
7
|
+
partitioning and mapping, on metrics for performance estimation of embedded software
|
|
8
|
+
applications and on dynamic reconfigurable devices.
|
|
9
|
+
|
|
10
|
+
Documentation: https://github.com/ferrandi/PandA-bambu
|
|
11
|
+
|
|
12
|
+
Sources: https://github.com/ferrandi/PandA-bambu
|
|
13
|
+
|
|
14
|
+
Installation: https://panda.dei.polimi.it/?page_id=88
|
|
15
|
+
'''
|
|
16
|
+
|
|
17
|
+
from siliconcompiler.tools.bambu import convert
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
####################################################################
|
|
21
|
+
# Make Docs
|
|
22
|
+
####################################################################
|
|
23
|
+
def make_docs(chip):
|
|
24
|
+
convert.setup(chip)
|
|
25
|
+
return chip
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def parse_version(stdout):
|
|
29
|
+
# Long multiline output, but second-to-last line looks like:
|
|
30
|
+
# Version: PandA 0.9.6 - Revision 5e5e306b86383a7d85274d64977a3d71fdcff4fe-main
|
|
31
|
+
version_line = stdout.split('\n')[-3]
|
|
32
|
+
return version_line.split()[2]
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
import shutil
|
|
3
|
-
from siliconcompiler import
|
|
4
|
+
from siliconcompiler.utils import sc_open
|
|
5
|
+
from siliconcompiler.tools._common.asic import set_tool_task_var, set_tool_task_lib_var, get_mainlib
|
|
6
|
+
from siliconcompiler.tools._common.asic_clock import get_clock_period, add_clock_requirements
|
|
4
7
|
from siliconcompiler.tools._common import \
|
|
5
8
|
add_frontend_requires, add_require_input, get_frontend_options, get_input_files, \
|
|
6
|
-
get_tool_task, has_input_files
|
|
9
|
+
get_tool_task, has_input_files, record_metric
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def make_docs(chip):
|
|
13
|
+
from siliconcompiler.targets import freepdk45_demo
|
|
14
|
+
chip.use(freepdk45_demo)
|
|
15
|
+
chip.input('<design>.c')
|
|
16
|
+
return setup(chip)
|
|
7
17
|
|
|
8
18
|
|
|
9
19
|
def setup(chip):
|
|
@@ -11,13 +21,13 @@ def setup(chip):
|
|
|
11
21
|
Performs high level synthesis to generate a verilog output
|
|
12
22
|
'''
|
|
13
23
|
|
|
14
|
-
if not has_input_files(chip, 'input', 'hll', 'c')
|
|
15
|
-
|
|
24
|
+
if not has_input_files(chip, 'input', 'hll', 'c') and \
|
|
25
|
+
not has_input_files(chip, 'input', 'hll', 'llvm'):
|
|
26
|
+
return "no files in [input,hll,c] or [input,hll,llvm]"
|
|
16
27
|
|
|
17
|
-
tool = 'bambu'
|
|
18
28
|
step = chip.get('arg', 'step')
|
|
19
29
|
index = chip.get('arg', 'index')
|
|
20
|
-
|
|
30
|
+
tool, task = get_tool_task(chip, step, index)
|
|
21
31
|
|
|
22
32
|
# Standard Setup
|
|
23
33
|
refdir = 'tools/' + tool
|
|
@@ -28,24 +38,41 @@ def setup(chip):
|
|
|
28
38
|
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
29
39
|
step=step, index=index,
|
|
30
40
|
package='siliconcompiler', clobber=False)
|
|
31
|
-
chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
|
|
32
|
-
step=step, index=index, clobber=False)
|
|
33
41
|
|
|
34
42
|
# Input/Output requirements
|
|
35
43
|
chip.add('tool', tool, 'task', task, 'output', chip.top() + '.v', step=step, index=index)
|
|
36
44
|
|
|
45
|
+
add_clock_requirements(chip)
|
|
46
|
+
|
|
37
47
|
# Schema requirements
|
|
38
48
|
add_require_input(chip, 'input', 'hll', 'c')
|
|
49
|
+
add_require_input(chip, 'input', 'hll', 'llvm')
|
|
39
50
|
add_frontend_requires(chip, ['idir', 'define'])
|
|
40
51
|
|
|
52
|
+
set_tool_task_var(chip, 'device',
|
|
53
|
+
schelp="Device to use during bambu synthesis")
|
|
54
|
+
set_tool_task_lib_var(chip, 'memorychannels', default_value=1,
|
|
55
|
+
schelp="Number of memory channels available")
|
|
56
|
+
|
|
57
|
+
# Require clock conversion factor, from library units to ns
|
|
58
|
+
mainlib = get_mainlib(chip)
|
|
59
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
60
|
+
','.join(['library', mainlib, 'option', 'var', 'bambu_clock_multiplier']),
|
|
61
|
+
step=step, index=index)
|
|
62
|
+
|
|
63
|
+
set_tool_task_var(chip, 'clock_multiplier',
|
|
64
|
+
schelp="Clock multiplier used to convert library units to ns")
|
|
65
|
+
|
|
41
66
|
|
|
42
67
|
################################
|
|
43
68
|
# Custom runtime options
|
|
44
69
|
################################
|
|
45
70
|
def runtime_options(chip):
|
|
46
|
-
|
|
71
|
+
step = chip.get('arg', 'step')
|
|
72
|
+
index = chip.get('arg', 'index')
|
|
73
|
+
tool, task = get_tool_task(chip, step, index)
|
|
47
74
|
|
|
48
|
-
cmdlist
|
|
75
|
+
cmdlist = []
|
|
49
76
|
|
|
50
77
|
opts = get_frontend_options(chip, ['idir', 'define'])
|
|
51
78
|
|
|
@@ -55,11 +82,34 @@ def runtime_options(chip):
|
|
|
55
82
|
cmdlist.append('-D' + value)
|
|
56
83
|
for value in get_input_files(chip, 'input', 'hll', 'c'):
|
|
57
84
|
cmdlist.append(value)
|
|
85
|
+
if not has_input_files(chip, 'input', 'hll', 'c'):
|
|
86
|
+
# Only use llvm if C is empty
|
|
87
|
+
for value in get_input_files(chip, 'input', 'hll', 'llvm'):
|
|
88
|
+
cmdlist.append(value)
|
|
58
89
|
|
|
90
|
+
cmdlist.append('--soft-float')
|
|
59
91
|
cmdlist.append('--memory-allocation-policy=NO_BRAM')
|
|
60
92
|
|
|
61
|
-
|
|
62
|
-
|
|
93
|
+
mem_channels = int(chip.get('tool', tool, 'task', task, 'var', 'memorychannels',
|
|
94
|
+
step=step, index=index)[0])
|
|
95
|
+
if mem_channels > 0:
|
|
96
|
+
cmdlist.append(f'--channels-number={mem_channels}')
|
|
97
|
+
|
|
98
|
+
mainlib = get_mainlib(chip)
|
|
99
|
+
clock_multiplier = float(chip.get('library', mainlib, 'option', 'var',
|
|
100
|
+
'bambu_clock_multiplier')[0])
|
|
101
|
+
clock_name, period = get_clock_period(chip, clock_units_multiplier=clock_multiplier)
|
|
102
|
+
if clock_name:
|
|
103
|
+
cmdlist.append(f'--clock-name={clock_name}')
|
|
104
|
+
if period:
|
|
105
|
+
cmdlist.append(f'--clock-period={period}')
|
|
106
|
+
|
|
107
|
+
cmdlist.append('--disable-function-proxy')
|
|
108
|
+
|
|
109
|
+
device = chip.get('tool', tool, 'task', task, 'var', 'device',
|
|
110
|
+
step=step, index=index)
|
|
111
|
+
if device:
|
|
112
|
+
cmdlist.append(f'--device={device[0]}')
|
|
63
113
|
|
|
64
114
|
cmdlist.append(f'--top-fname={chip.top(step, index)}')
|
|
65
115
|
|
|
@@ -76,3 +126,34 @@ def post_process(chip):
|
|
|
76
126
|
index = chip.get('arg', 'index')
|
|
77
127
|
|
|
78
128
|
shutil.copy2(f'{chip.top(step, index)}.v', os.path.join('outputs', f'{chip.top()}.v'))
|
|
129
|
+
|
|
130
|
+
ff = re.compile(fr"Total number of flip-flops in function {chip.top(step, index)}: (\d+)")
|
|
131
|
+
area = re.compile(r"Total estimated area: (\d+)")
|
|
132
|
+
fmax = re.compile(r"Estimated max frequency \(MHz\): (\d+\.?\d*)")
|
|
133
|
+
slack = re.compile(r"Minimum slack: (\d+\.?\d*)")
|
|
134
|
+
|
|
135
|
+
log_file = f"{step}.log"
|
|
136
|
+
with sc_open(log_file) as log:
|
|
137
|
+
for line in log:
|
|
138
|
+
ff_match = ff.findall(line)
|
|
139
|
+
area_match = area.findall(line)
|
|
140
|
+
fmax_match = fmax.findall(line)
|
|
141
|
+
slack_match = slack.findall(line)
|
|
142
|
+
if ff_match:
|
|
143
|
+
record_metric(chip, step, index, "registers", int(ff_match[0]), log_file)
|
|
144
|
+
if area_match:
|
|
145
|
+
record_metric(chip, step, index, "cellarea", float(area_match[0]), log_file,
|
|
146
|
+
source_unit='um^2')
|
|
147
|
+
if fmax_match:
|
|
148
|
+
record_metric(chip, step, index, "fmax", float(fmax_match[0]), log_file,
|
|
149
|
+
source_unit='MHz')
|
|
150
|
+
if slack_match:
|
|
151
|
+
slack_ns = float(slack_match[0])
|
|
152
|
+
if slack_ns >= 0:
|
|
153
|
+
record_metric(chip, step, index, "setupwns", 0, log_file,
|
|
154
|
+
source_unit='ns')
|
|
155
|
+
else:
|
|
156
|
+
record_metric(chip, step, index, "setupwns", slack_ns, log_file,
|
|
157
|
+
source_unit='ns')
|
|
158
|
+
record_metric(chip, step, index, "setupslack", slack_ns, log_file,
|
|
159
|
+
source_unit='ns')
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Bluespec is a high-level hardware description language. It has a variety of
|
|
3
|
+
advanced features including a powerful type system that can prevent errors
|
|
4
|
+
prior to synthesis time, and its most distinguishing feature, Guarded Atomic
|
|
5
|
+
Actions, allow you to define hardware components in a modular manner based
|
|
6
|
+
on their invariants, and let the compiler pick a scheduler.
|
|
7
|
+
|
|
8
|
+
Documentation: https://github.com/B-Lang-org/bsc#documentation
|
|
9
|
+
|
|
10
|
+
Sources: https://github.com/B-Lang-org/bsc
|
|
11
|
+
|
|
12
|
+
Installation: https://github.com/B-Lang-org/bsc#download
|
|
13
|
+
'''
|
|
14
|
+
|
|
15
|
+
from siliconcompiler.tools.bluespec import convert
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
####################################################################
|
|
19
|
+
# Make Docs
|
|
20
|
+
####################################################################
|
|
21
|
+
def make_docs(chip):
|
|
22
|
+
convert.setup(chip)
|
|
23
|
+
return chip
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
################################
|
|
27
|
+
# Setup Tool (pre executable)
|
|
28
|
+
################################
|
|
29
|
+
def parse_version(stdout):
|
|
30
|
+
# Examples:
|
|
31
|
+
# Bluespec Compiler, version 2021.12.1-27-g9a7d5e05 (build 9a7d5e05)
|
|
32
|
+
# Bluespec Compiler, version 2021.07 (build 4cac6eba)
|
|
33
|
+
|
|
34
|
+
long_version = stdout.split()[3]
|
|
35
|
+
return long_version.split('-')[0]
|
|
@@ -8,6 +8,7 @@ from siliconcompiler import sc_open
|
|
|
8
8
|
|
|
9
9
|
# Directory inside step/index dir to store bsc intermediate results.
|
|
10
10
|
VLOG_DIR = 'verilog'
|
|
11
|
+
BSC_DIR = 'bluespec'
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def setup(chip):
|
|
@@ -39,6 +40,7 @@ def setup(chip):
|
|
|
39
40
|
|
|
40
41
|
# Input/Output requirements
|
|
41
42
|
chip.add('tool', tool, 'task', task, 'output', chip.top() + '.v', step=step, index=index)
|
|
43
|
+
chip.add('tool', tool, 'task', task, 'output', chip.top() + '.dot', step=step, index=index)
|
|
42
44
|
|
|
43
45
|
# Schema requirements
|
|
44
46
|
add_require_input(chip, 'input', 'hll', 'bsv')
|
|
@@ -50,9 +52,10 @@ def setup(chip):
|
|
|
50
52
|
################################
|
|
51
53
|
def pre_process(chip):
|
|
52
54
|
# bsc requires its output directory exists before being called.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
for path in (VLOG_DIR, BSC_DIR):
|
|
56
|
+
if os.path.isdir(path):
|
|
57
|
+
shutil.rmtree(path)
|
|
58
|
+
os.makedirs(path)
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
################################
|
|
@@ -68,7 +71,13 @@ def runtime_options(chip):
|
|
|
68
71
|
|
|
69
72
|
cmdlist.append('-verilog')
|
|
70
73
|
cmdlist.append(f'-vdir {VLOG_DIR}')
|
|
74
|
+
cmdlist.append(f'-bdir {BSC_DIR}')
|
|
75
|
+
cmdlist.append('-info-dir reports')
|
|
71
76
|
cmdlist.append('-u')
|
|
77
|
+
cmdlist.append('-v')
|
|
78
|
+
|
|
79
|
+
cmdlist.append('-show-module-use')
|
|
80
|
+
cmdlist.append('-sched-dot')
|
|
72
81
|
|
|
73
82
|
cmdlist.append(f'-g {chip.top(step, index)}')
|
|
74
83
|
|
|
@@ -95,10 +104,40 @@ def post_process(chip):
|
|
|
95
104
|
''' Tool specific function to run after step execution
|
|
96
105
|
'''
|
|
97
106
|
|
|
107
|
+
step = chip.get('arg', 'step')
|
|
108
|
+
index = chip.get('arg', 'index')
|
|
109
|
+
|
|
110
|
+
shutil.copyfile(f"reports/{chip.top(step, index)}_combined_full.dot",
|
|
111
|
+
f"outputs/{chip.top()}.dot")
|
|
112
|
+
|
|
113
|
+
extra_modules = set()
|
|
114
|
+
use_file = os.path.join(VLOG_DIR, f"{chip.top(step, index)}.use")
|
|
115
|
+
if os.path.exists(use_file):
|
|
116
|
+
BSC_BASE = os.path.dirname(
|
|
117
|
+
os.path.dirname(
|
|
118
|
+
chip.get('record', 'toolpath', step=step, index=index)))
|
|
119
|
+
BSC_LIB = os.path.join(BSC_BASE, "lib", "Verilog")
|
|
120
|
+
|
|
121
|
+
with sc_open(use_file) as f:
|
|
122
|
+
for module in f:
|
|
123
|
+
module = module.strip()
|
|
124
|
+
mod_path = os.path.join(BSC_LIB, f"{module}.v")
|
|
125
|
+
if os.path.exists(mod_path):
|
|
126
|
+
extra_modules.add(mod_path)
|
|
127
|
+
else:
|
|
128
|
+
chip.logger.warn(f"Unable to find module {module} source files at: {BSC_LIB}")
|
|
129
|
+
|
|
98
130
|
# bsc outputs each compiled module to its own Verilog file, so we
|
|
99
131
|
# concatenate them all to create a pickled output we can pass along.
|
|
100
132
|
design = chip.top()
|
|
101
133
|
with open(os.path.join('outputs', f'{design}.v'), 'w') as pickled_vlog:
|
|
102
134
|
for src in os.listdir(VLOG_DIR):
|
|
103
|
-
|
|
104
|
-
|
|
135
|
+
if src.endswith(".v"):
|
|
136
|
+
with sc_open(os.path.join(VLOG_DIR, src)) as vlog_mod:
|
|
137
|
+
pickled_vlog.write(vlog_mod.read())
|
|
138
|
+
|
|
139
|
+
pickled_vlog.write("\n")
|
|
140
|
+
pickled_vlog.write("// Bluespec imports\n\n")
|
|
141
|
+
for vfile in extra_modules:
|
|
142
|
+
with sc_open(os.path.join(BSC_LIB, vfile)) as vlog_mod:
|
|
143
|
+
pickled_vlog.write(vlog_mod.read() + "\n")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Graphviz is open source graph visualization software.
|
|
3
|
+
Graph visualization is a way of representing structural information as diagrams
|
|
4
|
+
of abstract graphs and networks.
|
|
5
|
+
It has important applications in networking, bioinformatics, software engineering,
|
|
6
|
+
database and web design, machine learning, and in visual interfaces for other
|
|
7
|
+
technical domains.
|
|
8
|
+
'''
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def make_docs(chip):
|
|
12
|
+
return chip
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import graphviz
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from siliconcompiler import sc_open
|
|
5
|
+
from siliconcompiler.tools._common import get_tool_task
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def setup(chip):
|
|
9
|
+
'''
|
|
10
|
+
Generate a screenshot of a dot file
|
|
11
|
+
'''
|
|
12
|
+
|
|
13
|
+
step = chip.get('arg', 'step')
|
|
14
|
+
index = chip.get('arg', 'index')
|
|
15
|
+
tool, task = get_tool_task(chip, step, index)
|
|
16
|
+
|
|
17
|
+
chip.set('tool', tool, 'task', task, 'threads', 1, step=step, index=index)
|
|
18
|
+
|
|
19
|
+
chip.add('tool', tool, 'task', task, 'output', chip.top() + '.png', step=step, index=index)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def run(chip):
|
|
23
|
+
step = chip.get('arg', 'step')
|
|
24
|
+
index = chip.get('arg', 'index')
|
|
25
|
+
tool, task = get_tool_task(chip, step, index)
|
|
26
|
+
|
|
27
|
+
if os.path.exists(f'inputs/{chip.top()}.dot'):
|
|
28
|
+
file = f'inputs/{chip.top()}.dot'
|
|
29
|
+
elif os.path.exists(f'inputs/{chip.top()}.xdot'):
|
|
30
|
+
file = f'inputs/{chip.top()}.xdot'
|
|
31
|
+
elif chip.valid('tool', tool, 'task', task, 'var', 'show_filepath') and \
|
|
32
|
+
chip.get('tool', tool, 'task', task, 'var', 'show_filepath', step=step, index=index):
|
|
33
|
+
file = chip.get('tool', tool, 'task', task, 'var', 'show_filepath',
|
|
34
|
+
step=step, index=index)[0]
|
|
35
|
+
else:
|
|
36
|
+
file = chip.find_files('input', 'image', 'dot', step=step, index=index)[0]
|
|
37
|
+
|
|
38
|
+
with sc_open(file) as dot:
|
|
39
|
+
dot_content = dot.read()
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
dot = graphviz.Source(dot_content, format="png")
|
|
43
|
+
dot.render(filename=f"outputs/{chip.top()}", cleanup=True)
|
|
44
|
+
pass
|
|
45
|
+
except graphviz.ExecutableNotFound:
|
|
46
|
+
return 1
|
|
47
|
+
|
|
48
|
+
return 0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from PIL import Image
|
|
2
|
+
from siliconcompiler.tools.graphviz import screenshot
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def setup(chip):
|
|
6
|
+
'''
|
|
7
|
+
Show a graphviz dot file
|
|
8
|
+
'''
|
|
9
|
+
|
|
10
|
+
screenshot.setup(chip)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def run(chip):
|
|
14
|
+
screenshot_ret = screenshot.run(chip)
|
|
15
|
+
if screenshot_ret != 0:
|
|
16
|
+
return screenshot_ret
|
|
17
|
+
|
|
18
|
+
Image.open(f"outputs/{chip.top()}.png").show()
|
|
19
|
+
|
|
20
|
+
return 0
|
|
@@ -128,6 +128,8 @@ def extract_metrics(chip):
|
|
|
128
128
|
"drvs": [
|
|
129
129
|
"timing/drv_violators.rpt",
|
|
130
130
|
"floating_nets.rpt",
|
|
131
|
+
"overdriven_nets.rpt",
|
|
132
|
+
"overdriven_nets_with_parallel.rpt",
|
|
131
133
|
f"{chip.design}_antenna.rpt",
|
|
132
134
|
f"{chip.design}_antenna_post_repair.rpt"
|
|
133
135
|
],
|
|
@@ -148,6 +150,10 @@ def extract_metrics(chip):
|
|
|
148
150
|
|
|
149
151
|
metrics_file = "reports/metrics.json"
|
|
150
152
|
|
|
153
|
+
if not os.path.exists(metrics_file):
|
|
154
|
+
chip.logger.warning("OpenROAD metrics file is missing")
|
|
155
|
+
return
|
|
156
|
+
|
|
151
157
|
def get_metric_sources(metric):
|
|
152
158
|
metric_sources = [metrics_file]
|
|
153
159
|
if metric in metric_reports:
|
|
@@ -277,6 +283,10 @@ def extract_metrics(chip):
|
|
|
277
283
|
'sc__metric__timing__drv__max_slew',
|
|
278
284
|
'sc__metric__timing__drv__max_cap',
|
|
279
285
|
'sc__metric__timing__drv__max_fanout',
|
|
286
|
+
'sc__metric__timing__drv__max_fanout',
|
|
287
|
+
'sc__metric__timing__drv__floating__nets',
|
|
288
|
+
'sc__metric__timing__drv__floating__pins',
|
|
289
|
+
'sc__metric__timing__drv__overdriven__nets',
|
|
280
290
|
'sc__metric__antenna__violating__nets',
|
|
281
291
|
'sc__metric__antenna__violating__pins']:
|
|
282
292
|
if metric in metrics:
|
|
@@ -572,6 +582,13 @@ def define_rsz_params(chip):
|
|
|
572
582
|
default_value='100',
|
|
573
583
|
schelp='percentage of violating nets to attempt to repair (0 - 100)')
|
|
574
584
|
|
|
585
|
+
set_tool_task_var(chip, param_key='rsz_skip_recover_power',
|
|
586
|
+
default_value=False,
|
|
587
|
+
schelp='skip power recovery')
|
|
588
|
+
set_tool_task_var(chip, param_key='rsz_recover_power',
|
|
589
|
+
default_value=100,
|
|
590
|
+
schelp='percentage of paths to attempt to recover power (0 - 100)')
|
|
591
|
+
|
|
575
592
|
step = chip.get('arg', 'step')
|
|
576
593
|
index = chip.get('arg', 'index')
|
|
577
594
|
tool, task = get_tool_task(chip, step, index)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from siliconcompiler.tools._common import input_provides, add_common_file, get_tool_task
|
|
2
|
-
from siliconcompiler.tools._common.asic import set_tool_task_var
|
|
2
|
+
from siliconcompiler.tools._common.asic import set_tool_task_var, get_mainlib
|
|
3
3
|
|
|
4
4
|
from siliconcompiler.tools.openroad._apr import setup as apr_setup
|
|
5
5
|
from siliconcompiler.tools.openroad._apr import set_reports, set_pnr_inputs, set_pnr_outputs
|
|
@@ -74,6 +74,8 @@ def setup(chip):
|
|
|
74
74
|
'power'
|
|
75
75
|
])
|
|
76
76
|
|
|
77
|
+
mainlib = get_mainlib(chip)
|
|
78
|
+
|
|
77
79
|
# Setup required
|
|
78
80
|
for component in chip.getkeys('constraint', 'component'):
|
|
79
81
|
for key in chip.getkeys('constraint', 'component', component):
|
|
@@ -92,6 +94,10 @@ def setup(chip):
|
|
|
92
94
|
chip.add('tool', tool, 'task', task, 'require',
|
|
93
95
|
','.join(['constraint', ifp]),
|
|
94
96
|
step=step, index=index)
|
|
97
|
+
if chip.valid('library', mainlib, 'option', 'file', 'openroad_tracks'):
|
|
98
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
99
|
+
','.join(['library', mainlib, 'option', 'file', 'openroad_tracks']),
|
|
100
|
+
step=step, index=index)
|
|
95
101
|
|
|
96
102
|
|
|
97
103
|
def pre_process(chip):
|
|
@@ -40,10 +40,18 @@ def setup(chip):
|
|
|
40
40
|
|
|
41
41
|
set_reports(chip, [
|
|
42
42
|
'setup',
|
|
43
|
-
'unconstrained'
|
|
44
|
-
'power'
|
|
43
|
+
'unconstrained'
|
|
45
44
|
])
|
|
46
45
|
|
|
46
|
+
chip.set('tool', tool, 'task', task, 'file', 'rtlmp_constraints',
|
|
47
|
+
'contraints script for macro placement',
|
|
48
|
+
field='help')
|
|
49
|
+
|
|
50
|
+
if chip.get('tool', tool, 'task', task, 'file', 'rtlmp_constraints', step=step, index=index):
|
|
51
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
52
|
+
",".join(['tool', tool, 'task', task, 'file', 'rtlmp_constraints']),
|
|
53
|
+
step=step, index=index)
|
|
54
|
+
|
|
47
55
|
|
|
48
56
|
def pre_process(chip):
|
|
49
57
|
step = chip.get('arg', 'step')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from siliconcompiler import NodeStatus
|
|
2
2
|
|
|
3
3
|
from siliconcompiler.tools._common import get_tool_task, has_pre_post_script
|
|
4
|
+
from siliconcompiler.tools._common.asic import set_tool_task_var
|
|
4
5
|
|
|
5
6
|
from siliconcompiler.tools.openroad._apr import setup as apr_setup
|
|
6
7
|
from siliconcompiler.tools.openroad._apr import set_reports, set_pnr_inputs, set_pnr_outputs
|
|
@@ -39,6 +40,11 @@ def setup(chip):
|
|
|
39
40
|
define_pdn_params(chip)
|
|
40
41
|
define_psm_params(chip)
|
|
41
42
|
|
|
43
|
+
set_tool_task_var(chip, param_key='fixed_pin_keepout',
|
|
44
|
+
default_value=0,
|
|
45
|
+
schelp='if > 0, applies a blockage in multiples of the routing pitch '
|
|
46
|
+
'to each fixed pin to ensure there is room for routing.')
|
|
47
|
+
|
|
42
48
|
set_reports(chip, [])
|
|
43
49
|
|
|
44
50
|
|
|
@@ -91,5 +91,6 @@ if { [llength $openroad_dont_touch] > 0 } {
|
|
|
91
91
|
# set don't touch list
|
|
92
92
|
set_dont_touch $openroad_dont_touch
|
|
93
93
|
}
|
|
94
|
-
tee -file reports/dont_touch.start.rpt {report_dont_touch}
|
|
95
|
-
tee -file reports/dont_use.start.rpt {report_dont_use}
|
|
94
|
+
tee -quiet -file reports/dont_touch.start.rpt {report_dont_touch}
|
|
95
|
+
tee -quiet -file reports/dont_use.start.rpt {report_dont_use}
|
|
96
|
+
tee -file reports/global_connections.start.rpt {report_global_connect}
|
|
@@ -15,6 +15,8 @@ source -echo "$sc_refdir/apr/preamble.tcl"
|
|
|
15
15
|
# Detailed Routing
|
|
16
16
|
###############################
|
|
17
17
|
|
|
18
|
+
sc_setup_detailed_route
|
|
19
|
+
|
|
18
20
|
set drt_arguments []
|
|
19
21
|
if { [lindex [sc_cfg_tool_task_get {var} drt_disable_via_gen] 0] == "true" } {
|
|
20
22
|
lappend drt_arguments "-disable_via_gen"
|