siliconcompiler 0.29.3__py3-none-any.whl → 0.29.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/sc_install.py +18 -3
- siliconcompiler/remote/client.py +3 -0
- siliconcompiler/scheduler/__init__.py +9 -3
- siliconcompiler/tools/__init__.py +1 -1
- 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/openroad/_apr.py +11 -0
- siliconcompiler/tools/openroad/fillmetal_insertion.py +0 -1
- siliconcompiler/tools/openroad/init_floorplan.py +7 -1
- siliconcompiler/tools/openroad/macro_placement.py +1 -2
- siliconcompiler/tools/openroad/pin_placement.py +0 -1
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +24 -0
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +2 -1
- siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +0 -13
- 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 +2 -2
- 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-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +1 -1
- siliconcompiler/utils/__init__.py +2 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/METADATA +5 -5
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/RECORD +41 -40
- siliconcompiler/tools/bambu/bambu.py +0 -32
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/top_level.txt +0 -0
siliconcompiler/_metadata.py
CHANGED
|
@@ -73,16 +73,18 @@ def show_tool(tool, script):
|
|
|
73
73
|
def _get_os_name():
|
|
74
74
|
machine_info = _get_machine_info()
|
|
75
75
|
system = machine_info.get('system', "").lower()
|
|
76
|
-
distro = machine_info.get('distro', "").lower()
|
|
77
|
-
osversion = machine_info.get('osversion', "").lower()
|
|
78
76
|
if system == 'linux':
|
|
77
|
+
distro = machine_info.get('distro', "").lower()
|
|
79
78
|
if distro == 'ubuntu':
|
|
79
|
+
osversion = machine_info.get('osversion', "").lower()
|
|
80
80
|
version, _ = osversion.split('.')
|
|
81
81
|
return f"{distro}{version}"
|
|
82
82
|
elif distro == 'rocky':
|
|
83
|
+
osversion = machine_info.get('osversion', "").lower()
|
|
83
84
|
version, _ = osversion.split('.')
|
|
84
85
|
return f"rhel{version}"
|
|
85
86
|
elif distro == 'rhel':
|
|
87
|
+
osversion = machine_info.get('osversion', "").lower()
|
|
86
88
|
version, _ = osversion.split('.')
|
|
87
89
|
return f"rhel{version}"
|
|
88
90
|
return None
|
|
@@ -134,6 +136,10 @@ def _recommended_tool_groups(tools):
|
|
|
134
136
|
for group, group_tools in groups.items():
|
|
135
137
|
if all([tool in tools for tool in group_tools]):
|
|
136
138
|
filter_groups[group] = group_tools
|
|
139
|
+
else:
|
|
140
|
+
missing = sorted([tool for tool in group_tools if tool not in tools])
|
|
141
|
+
filter_groups[group] = f"{group} group is not available for {_get_os_name()} " \
|
|
142
|
+
f"due to lack of support for the following tools: {', '.join(missing)}"
|
|
137
143
|
return filter_groups
|
|
138
144
|
|
|
139
145
|
|
|
@@ -172,6 +178,11 @@ To system debugging information (this should only be used to debug):
|
|
|
172
178
|
|
|
173
179
|
tools = _get_tools_list()
|
|
174
180
|
|
|
181
|
+
if _get_os_name() is None:
|
|
182
|
+
print("Unsupported operating system", file=sys.stderr)
|
|
183
|
+
print_machine_info()
|
|
184
|
+
return 1
|
|
185
|
+
|
|
175
186
|
tool_choices = ChoiceOptional(tools.keys())
|
|
176
187
|
parser.add_argument(
|
|
177
188
|
"tool",
|
|
@@ -220,7 +231,11 @@ To system debugging information (this should only be used to debug):
|
|
|
220
231
|
args.tool = list(args.tool)
|
|
221
232
|
if args.group:
|
|
222
233
|
for group in args.group:
|
|
223
|
-
|
|
234
|
+
if isinstance(tool_groups[group], str):
|
|
235
|
+
print(tool_groups[group], file=sys.stderr)
|
|
236
|
+
return 1
|
|
237
|
+
else:
|
|
238
|
+
args.tool.extend(tool_groups[group])
|
|
224
239
|
|
|
225
240
|
tools_handled = set()
|
|
226
241
|
for tool in args.tool:
|
siliconcompiler/remote/client.py
CHANGED
|
@@ -477,6 +477,9 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
|
|
|
477
477
|
# Flush file to ensure everything is written
|
|
478
478
|
upload_file.flush()
|
|
479
479
|
|
|
480
|
+
# We no longer need the collected files
|
|
481
|
+
shutil.rmtree(self.__chip._getcollectdir(jobname=self.__chip.get('option', 'jobname')))
|
|
482
|
+
|
|
480
483
|
if 'pre_upload' in remote_status:
|
|
481
484
|
self.__logger.info(remote_status['pre_upload']['message'])
|
|
482
485
|
time.sleep(remote_status['pre_upload']['delay'])
|
|
@@ -1628,8 +1628,14 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1628
1628
|
# Update dashboard if the manifest changed
|
|
1629
1629
|
chip._dash.update_manifest()
|
|
1630
1630
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1631
|
+
if len(running_nodes) == 1:
|
|
1632
|
+
# if there is only one node running, just join the thread
|
|
1633
|
+
running_node = list(running_nodes.keys())[0]
|
|
1634
|
+
processes[running_node]["proc"].join()
|
|
1635
|
+
elif len(running_nodes) > 1:
|
|
1636
|
+
# if there are more than 1, join the first with a timeout
|
|
1637
|
+
running_node = list(running_nodes.keys())[0]
|
|
1638
|
+
processes[running_node]["proc"].join(timeout=0.1)
|
|
1633
1639
|
|
|
1634
1640
|
|
|
1635
1641
|
def _process_completed_nodes(chip, processes, running_nodes):
|
|
@@ -1949,7 +1955,7 @@ def check_node_inputs(chip, step, index):
|
|
|
1949
1955
|
step=check_step, index=check_index)
|
|
1950
1956
|
|
|
1951
1957
|
if check_hash != prev_hash:
|
|
1952
|
-
print_warning(key)
|
|
1958
|
+
print_warning(key, "file hash")
|
|
1953
1959
|
return False
|
|
1954
1960
|
else:
|
|
1955
1961
|
# check timestamps on current files
|
|
@@ -194,6 +194,9 @@ def set_tool_task_lib_var(chip,
|
|
|
194
194
|
|
|
195
195
|
values.update(chip.get(*lib_key, step=get_step, index=get_index))
|
|
196
196
|
|
|
197
|
+
if default_value and not check_value(values):
|
|
198
|
+
values = default_value
|
|
199
|
+
|
|
197
200
|
if check_value(values):
|
|
198
201
|
chip.set('tool', tool, 'task', task, 'var', param_key, values,
|
|
199
202
|
step=step, index=index, clobber=False)
|
|
@@ -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')
|
|
@@ -148,6 +148,10 @@ def extract_metrics(chip):
|
|
|
148
148
|
|
|
149
149
|
metrics_file = "reports/metrics.json"
|
|
150
150
|
|
|
151
|
+
if not os.path.exists(metrics_file):
|
|
152
|
+
chip.logger.warning("OpenROAD metrics file is missing")
|
|
153
|
+
return
|
|
154
|
+
|
|
151
155
|
def get_metric_sources(metric):
|
|
152
156
|
metric_sources = [metrics_file]
|
|
153
157
|
if metric in metric_reports:
|
|
@@ -572,6 +576,13 @@ def define_rsz_params(chip):
|
|
|
572
576
|
default_value='100',
|
|
573
577
|
schelp='percentage of violating nets to attempt to repair (0 - 100)')
|
|
574
578
|
|
|
579
|
+
set_tool_task_var(chip, param_key='rsz_skip_recover_power',
|
|
580
|
+
default_value=False,
|
|
581
|
+
schelp='skip power recovery')
|
|
582
|
+
set_tool_task_var(chip, param_key='rsz_recover_power',
|
|
583
|
+
default_value=100,
|
|
584
|
+
schelp='percentage of paths to attempt to recover power (0 - 100)')
|
|
585
|
+
|
|
575
586
|
step = chip.get('arg', 'step')
|
|
576
587
|
index = chip.get('arg', 'index')
|
|
577
588
|
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):
|
|
@@ -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}
|
|
@@ -33,6 +33,7 @@ foreach pdnconfig [sc_cfg_tool_task_get {file} pdn_config] {
|
|
|
33
33
|
|
|
34
34
|
lappend pdn_files $pdnconfig
|
|
35
35
|
}
|
|
36
|
+
tee -quiet -file reports/power_grid_configuration.rpt {pdngen -report_only}
|
|
36
37
|
pdngen -failed_via_report "reports/${sc_design}_pdngen_failed_vias.rpt"
|
|
37
38
|
|
|
38
39
|
###############################
|
|
@@ -20,6 +20,7 @@ set rsz_hold_slack_margin [lindex [sc_cfg_tool_task_get {var} rsz_hold_slack_mar
|
|
|
20
20
|
set rsz_slew_margin [lindex [sc_cfg_tool_task_get {var} rsz_slew_margin] 0]
|
|
21
21
|
set rsz_cap_margin [lindex [sc_cfg_tool_task_get {var} rsz_cap_margin] 0]
|
|
22
22
|
set rsz_repair_tns [lindex [sc_cfg_tool_task_get {var} rsz_repair_tns] 0]
|
|
23
|
+
set rsz_recover_power [lindex [sc_cfg_tool_task_get {var} rsz_recover_power] 0]
|
|
23
24
|
|
|
24
25
|
set repair_timing_args []
|
|
25
26
|
if { [lindex [sc_cfg_tool_task_get {var} rsz_skip_pin_swap] 0] == "true" } {
|
|
@@ -77,6 +78,29 @@ if { [lindex [sc_cfg_tool_task_get var rsz_skip_hold_repair] 0] != "true" } {
|
|
|
77
78
|
sc_set_dont_use
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
if { [lindex [sc_cfg_tool_task_get var rsz_skip_recover_power] 0] != "true" } {
|
|
82
|
+
###############################
|
|
83
|
+
# Recover power
|
|
84
|
+
###############################
|
|
85
|
+
|
|
86
|
+
estimate_parasitics -placement
|
|
87
|
+
|
|
88
|
+
# Enable cells
|
|
89
|
+
sc_set_dont_use -hold -scanchain -multibit -report dont_use.repair_timing.power
|
|
90
|
+
|
|
91
|
+
repair_timing \
|
|
92
|
+
-recover_power $rsz_recover_power \
|
|
93
|
+
-verbose \
|
|
94
|
+
-setup_margin $rsz_setup_slack_margin \
|
|
95
|
+
-hold_margin $rsz_hold_slack_margin \
|
|
96
|
+
{*}$repair_timing_args
|
|
97
|
+
|
|
98
|
+
sc_detailed_placement
|
|
99
|
+
|
|
100
|
+
# Restore dont use
|
|
101
|
+
sc_set_dont_use
|
|
102
|
+
}
|
|
103
|
+
|
|
80
104
|
global_connect
|
|
81
105
|
|
|
82
106
|
# estimate for metrics
|
|
@@ -758,6 +758,7 @@ proc sc_set_dont_use { args } {
|
|
|
758
758
|
}
|
|
759
759
|
|
|
760
760
|
if { [info exists keys(-report)] } {
|
|
761
|
-
|
|
761
|
+
puts "Dont use report: reports/$keys(-report).rpt"
|
|
762
|
+
tee -quiet -file reports/$keys(-report).rpt {report_dont_use}
|
|
762
763
|
}
|
|
763
764
|
}
|
|
@@ -168,17 +168,4 @@ foreach markerdb [[ord::get_db_block] getMarkerCategories] {
|
|
|
168
168
|
|
|
169
169
|
utl::push_metrics_stage "sc__cellarea__{}"
|
|
170
170
|
tee -file reports/cell_usage.rpt {report_cell_usage -verbose}
|
|
171
|
-
|
|
172
|
-
foreach modinst [[ord::get_db_block] getModInsts] {
|
|
173
|
-
tee -quiet -append -file reports/cell_usage.rpt { puts "" }
|
|
174
|
-
tee -quiet -append -file reports/cell_usage.rpt {
|
|
175
|
-
puts "########################################################"
|
|
176
|
-
}
|
|
177
|
-
tee -quiet -append -file reports/cell_usage.rpt { puts "" }
|
|
178
|
-
|
|
179
|
-
utl::metric "design__instance__name__in_module:[[$modinst getMaster] getName]" \
|
|
180
|
-
[$modinst getHierarchicalName]
|
|
181
|
-
tee -quiet -append -file reports/cell_usage.rpt \
|
|
182
|
-
"report_cell_usage -verbose [$modinst getHierarchicalName]"
|
|
183
|
-
}
|
|
184
171
|
utl::pop_metrics_stage
|
|
@@ -120,6 +120,7 @@ def common_runtime_options(chip):
|
|
|
120
120
|
###############################
|
|
121
121
|
# Set up user-provided parameters to ensure we elaborate the correct modules
|
|
122
122
|
for param, value in opts['param']:
|
|
123
|
+
value = value.replace('"', '\\"')
|
|
123
124
|
options.append(f'-G {param}={value}')
|
|
124
125
|
|
|
125
126
|
return options
|