siliconcompiler 0.29.2__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 +19 -4
- siliconcompiler/core.py +8 -3
- siliconcompiler/flowgraph.py +23 -5
- siliconcompiler/remote/client.py +3 -0
- siliconcompiler/scheduler/__init__.py +30 -12
- 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 -11
- siliconcompiler/tools/bluespec/convert.py +2 -1
- siliconcompiler/tools/chisel/convert.py +2 -1
- siliconcompiler/tools/genfasm/bitstream.py +2 -2
- siliconcompiler/tools/ghdl/convert.py +2 -2
- siliconcompiler/tools/gtkwave/show.py +2 -1
- siliconcompiler/tools/icarus/compile.py +2 -2
- siliconcompiler/tools/klayout/drc.py +2 -1
- siliconcompiler/tools/magic/magic.py +1 -1
- siliconcompiler/tools/netgen/lvs.py +2 -1
- siliconcompiler/tools/openroad/_apr.py +16 -4
- 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/rdlroute.py +2 -2
- 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_macro_placement.tcl +78 -94
- siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +12 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +24 -0
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +3 -2
- siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +4 -13
- siliconcompiler/tools/openroad/scripts/common/write_data.tcl +2 -5
- siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +3 -0
- siliconcompiler/tools/openroad/scripts/common/write_data_timing.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +1 -1
- siliconcompiler/tools/opensta/__init__.py +2 -2
- siliconcompiler/tools/opensta/report_libraries.py +2 -2
- siliconcompiler/tools/opensta/timing.py +2 -1
- siliconcompiler/tools/slang/__init__.py +79 -2
- siliconcompiler/tools/slang/elaborate.py +46 -0
- siliconcompiler/tools/slang/lint.py +10 -76
- siliconcompiler/tools/surelog/parse.py +1 -1
- siliconcompiler/tools/sv2v/convert.py +2 -2
- siliconcompiler/tools/template/template.py +2 -2
- siliconcompiler/tools/verilator/verilator.py +3 -1
- siliconcompiler/tools/vivado/vivado.py +2 -1
- siliconcompiler/tools/vpr/place.py +2 -2
- siliconcompiler/tools/vpr/route.py +2 -2
- siliconcompiler/tools/vpr/show.py +2 -1
- siliconcompiler/tools/yosys/__init__.py +26 -23
- siliconcompiler/tools/yosys/procs.tcl +17 -0
- siliconcompiler/tools/yosys/syn_asic.py +20 -65
- siliconcompiler/tools/yosys/syn_asic.tcl +10 -51
- siliconcompiler/toolscripts/_tools.json +4 -4
- siliconcompiler/toolscripts/rhel8/install-slang.sh +0 -0
- siliconcompiler/toolscripts/rhel8/install-sv2v.sh +7 -1
- siliconcompiler/toolscripts/rhel8/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/rhel9/install-openroad.sh +34 -0
- siliconcompiler/toolscripts/rhel9/install-slang.sh +0 -0
- siliconcompiler/toolscripts/rhel9/install-sv2v.sh +7 -1
- siliconcompiler/toolscripts/rhel9/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +0 -0
- siliconcompiler/toolscripts/ubuntu20/install-surelog.sh +1 -0
- siliconcompiler/toolscripts/ubuntu20/install-sv2v.sh +7 -1
- siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu22/install-surelog.sh +7 -1
- siliconcompiler/toolscripts/ubuntu22/install-sv2v.sh +7 -1
- siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +1 -1
- siliconcompiler/toolscripts/ubuntu24/install-bambu.sh +3 -4
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +0 -0
- siliconcompiler/toolscripts/ubuntu24/install-surelog.sh +7 -1
- siliconcompiler/toolscripts/ubuntu24/install-sv2v.sh +7 -1
- siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +1 -1
- siliconcompiler/utils/__init__.py +24 -0
- siliconcompiler/utils/logging.py +67 -0
- {siliconcompiler-0.29.2.dist-info → siliconcompiler-0.29.4.dist-info}/METADATA +8 -8
- {siliconcompiler-0.29.2.dist-info → siliconcompiler-0.29.4.dist-info}/RECORD +80 -75
- siliconcompiler/tools/bambu/bambu.py +0 -32
- {siliconcompiler-0.29.2.dist-info → siliconcompiler-0.29.4.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.29.2.dist-info → siliconcompiler-0.29.4.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.29.2.dist-info → siliconcompiler-0.29.4.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.29.2.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
|
|
|
@@ -168,10 +174,15 @@ To system debugging information (this should only be used to debug):
|
|
|
168
174
|
parser = argparse.ArgumentParser(
|
|
169
175
|
prog=progname,
|
|
170
176
|
description=description,
|
|
171
|
-
formatter_class=argparse.
|
|
177
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
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/core.py
CHANGED
|
@@ -21,6 +21,7 @@ from siliconcompiler.remote import client
|
|
|
21
21
|
from siliconcompiler.schema import Schema, SCHEMA_VERSION
|
|
22
22
|
from siliconcompiler.schema import utils as schema_utils
|
|
23
23
|
from siliconcompiler import utils
|
|
24
|
+
from siliconcompiler.utils.logging import LoggerFormatter, ColorStreamFormatter
|
|
24
25
|
from siliconcompiler import _metadata
|
|
25
26
|
from siliconcompiler import NodeStatus, SiliconCompilerError
|
|
26
27
|
from siliconcompiler.report import _show_summary_table
|
|
@@ -225,7 +226,8 @@ class Chip:
|
|
|
225
226
|
else:
|
|
226
227
|
in_run = False
|
|
227
228
|
|
|
228
|
-
|
|
229
|
+
level_format = '%(levelname)-7s'
|
|
230
|
+
log_format = [level_format]
|
|
229
231
|
if loglevel == 'debug':
|
|
230
232
|
log_format.append('%(funcName)-10s')
|
|
231
233
|
log_format.append('%(lineno)-4s')
|
|
@@ -261,14 +263,17 @@ class Chip:
|
|
|
261
263
|
log_formatprefix = ""
|
|
262
264
|
|
|
263
265
|
log_format.append('%(message)s')
|
|
264
|
-
|
|
266
|
+
stream_logformat = log_formatprefix + ' | '.join(log_format[1:])
|
|
265
267
|
|
|
266
268
|
if not self.logger.hasHandlers():
|
|
267
269
|
stream_handler = logging.StreamHandler(stream=sys.stdout)
|
|
268
270
|
self.logger.addHandler(stream_handler)
|
|
269
271
|
|
|
270
272
|
for handler in self.logger.handlers:
|
|
271
|
-
|
|
273
|
+
if ColorStreamFormatter.supports_color(handler):
|
|
274
|
+
formatter = ColorStreamFormatter(log_formatprefix, level_format, stream_logformat)
|
|
275
|
+
else:
|
|
276
|
+
formatter = LoggerFormatter(log_formatprefix, level_format, stream_logformat)
|
|
272
277
|
handler.setFormatter(formatter)
|
|
273
278
|
|
|
274
279
|
self.logger.setLevel(schema_utils.translate_loglevel(loglevel))
|
siliconcompiler/flowgraph.py
CHANGED
|
@@ -205,18 +205,36 @@ def _get_flowgraph_execution_order(chip, flow, reverse=False):
|
|
|
205
205
|
else:
|
|
206
206
|
ex_map.setdefault((istep, iindex), set()).add((step, index))
|
|
207
207
|
|
|
208
|
+
rev_ex_map = {}
|
|
209
|
+
for node, edges in ex_map.items():
|
|
210
|
+
for step, index in edges:
|
|
211
|
+
rev_ex_map.setdefault((step, index), set()).add(node)
|
|
212
|
+
|
|
208
213
|
# Collect execution order of nodes
|
|
209
214
|
if reverse:
|
|
210
215
|
order = [set(_get_flowgraph_exit_nodes(chip, flow))]
|
|
211
216
|
else:
|
|
212
217
|
order = [set(_get_flowgraph_entry_nodes(chip, flow))]
|
|
213
218
|
|
|
219
|
+
visited = set()
|
|
214
220
|
while True:
|
|
215
221
|
next_level = set()
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
222
|
+
next_visited = set()
|
|
223
|
+
for step, index in sorted(order[-1]):
|
|
224
|
+
if (step, index) not in rev_ex_map:
|
|
225
|
+
# No edges so assume inputs are okay
|
|
226
|
+
inputs_valid = True
|
|
227
|
+
else:
|
|
228
|
+
inputs_valid = all([node in visited for node in rev_ex_map[(step, index)]])
|
|
229
|
+
|
|
230
|
+
if inputs_valid:
|
|
231
|
+
next_visited.add((step, index))
|
|
232
|
+
if (step, index) in ex_map:
|
|
233
|
+
next_level.update(ex_map.pop((step, index)))
|
|
234
|
+
else:
|
|
235
|
+
next_level.add((step, index))
|
|
236
|
+
|
|
237
|
+
visited.update(next_visited)
|
|
220
238
|
|
|
221
239
|
if not next_level:
|
|
222
240
|
break
|
|
@@ -233,7 +251,7 @@ def _get_flowgraph_execution_order(chip, flow, reverse=False):
|
|
|
233
251
|
|
|
234
252
|
exec_order.reverse()
|
|
235
253
|
|
|
236
|
-
return exec_order
|
|
254
|
+
return [sorted(level) for level in exec_order]
|
|
237
255
|
|
|
238
256
|
|
|
239
257
|
def get_executed_nodes(chip, flow):
|
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'])
|
|
@@ -55,6 +55,10 @@ def _get_callback(hook):
|
|
|
55
55
|
return None
|
|
56
56
|
|
|
57
57
|
|
|
58
|
+
# Max lines to print from failed node log
|
|
59
|
+
_failed_log_lines = 20
|
|
60
|
+
|
|
61
|
+
|
|
58
62
|
###############################################################################
|
|
59
63
|
class SiliconCompilerTimeout(Exception):
|
|
60
64
|
''' Minimal Exception wrapper used to raise sc timeout errors.
|
|
@@ -833,6 +837,8 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
|
|
|
833
837
|
is_stderr_log = chip.get('tool', tool, 'task', task, 'stderr', 'destination',
|
|
834
838
|
step=step, index=index) == 'log' and stderr_file != stdout_file
|
|
835
839
|
|
|
840
|
+
chip.logger.info(f'Running in {workdir}')
|
|
841
|
+
|
|
836
842
|
retcode = 0
|
|
837
843
|
cmdlist = []
|
|
838
844
|
cmd_args = []
|
|
@@ -877,7 +883,6 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
|
|
|
877
883
|
# Make record of tool options
|
|
878
884
|
__record_tool(chip, step, index, version, toolpath, cmd_args)
|
|
879
885
|
|
|
880
|
-
chip.logger.info('Running in %s', workdir)
|
|
881
886
|
chip.logger.info('%s', printable_cmd)
|
|
882
887
|
timeout = chip.get('option', 'timeout', step=step, index=index)
|
|
883
888
|
logfile = step + '.log'
|
|
@@ -988,10 +993,10 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
|
|
|
988
993
|
msg = f'Command failed with code {retcode}.'
|
|
989
994
|
if logfile:
|
|
990
995
|
if quiet:
|
|
991
|
-
# Print last
|
|
996
|
+
# Print last N lines of log when in quiet mode
|
|
992
997
|
with sc_open(logfile) as logfd:
|
|
993
998
|
loglines = logfd.read().splitlines()
|
|
994
|
-
for logline in loglines[-
|
|
999
|
+
for logline in loglines[-_failed_log_lines:]:
|
|
995
1000
|
chip.logger.error(logline)
|
|
996
1001
|
# No log file for pure-Python tools.
|
|
997
1002
|
msg += f' See log file {os.path.abspath(logfile)}'
|
|
@@ -1239,6 +1244,13 @@ def _finalizenode(chip, step, index, replay):
|
|
|
1239
1244
|
|
|
1240
1245
|
if not is_skipped:
|
|
1241
1246
|
_check_logfile(chip, step, index, quiet, run_func)
|
|
1247
|
+
|
|
1248
|
+
# Report metrics
|
|
1249
|
+
for metric in ['errors', 'warnings']:
|
|
1250
|
+
val = chip.get('metric', metric, step=step, index=index)
|
|
1251
|
+
if val is not None:
|
|
1252
|
+
chip.logger.info(f'Number of {metric}: {val}')
|
|
1253
|
+
|
|
1242
1254
|
_hash_files(chip, step, index)
|
|
1243
1255
|
|
|
1244
1256
|
# Capture wall runtime and cpu cores
|
|
@@ -1535,12 +1547,13 @@ def _check_node_dependencies(chip, node, deps, deps_was_successful):
|
|
|
1535
1547
|
def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
1536
1548
|
running_nodes = {}
|
|
1537
1549
|
max_parallel_run = chip.get('option', 'scheduler', 'maxnodes')
|
|
1538
|
-
|
|
1550
|
+
max_cores = utils.get_cores(chip)
|
|
1551
|
+
max_threads = utils.get_cores(chip)
|
|
1539
1552
|
if not max_parallel_run:
|
|
1540
|
-
max_parallel_run =
|
|
1553
|
+
max_parallel_run = utils.get_cores(chip)
|
|
1541
1554
|
|
|
1542
|
-
# clip max parallel jobs to 1 <= jobs <=
|
|
1543
|
-
max_parallel_run = max(1, min(max_parallel_run,
|
|
1555
|
+
# clip max parallel jobs to 1 <= jobs <= max_cores
|
|
1556
|
+
max_parallel_run = max(1, min(max_parallel_run, max_cores))
|
|
1544
1557
|
|
|
1545
1558
|
def allow_start(node):
|
|
1546
1559
|
if node not in local_processes:
|
|
@@ -1561,7 +1574,7 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1561
1574
|
# clamp to max_parallel to avoid getting locked up
|
|
1562
1575
|
requested_threads = max(1, min(requested_threads, max_threads))
|
|
1563
1576
|
|
|
1564
|
-
if requested_threads + sum(running_nodes.values()) >
|
|
1577
|
+
if requested_threads + sum(running_nodes.values()) > max_cores:
|
|
1565
1578
|
# delay until there are enough core available
|
|
1566
1579
|
return False, 0
|
|
1567
1580
|
|
|
@@ -1615,8 +1628,14 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
|
|
|
1615
1628
|
# Update dashboard if the manifest changed
|
|
1616
1629
|
chip._dash.update_manifest()
|
|
1617
1630
|
|
|
1618
|
-
|
|
1619
|
-
|
|
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)
|
|
1620
1639
|
|
|
1621
1640
|
|
|
1622
1641
|
def _process_completed_nodes(chip, processes, running_nodes):
|
|
@@ -1936,7 +1955,7 @@ def check_node_inputs(chip, step, index):
|
|
|
1936
1955
|
step=check_step, index=check_index)
|
|
1937
1956
|
|
|
1938
1957
|
if check_hash != prev_hash:
|
|
1939
|
-
print_warning(key)
|
|
1958
|
+
print_warning(key, "file hash")
|
|
1940
1959
|
return False
|
|
1941
1960
|
else:
|
|
1942
1961
|
# check timestamps on current files
|
|
@@ -2062,7 +2081,6 @@ def check_logfile(chip, jobname=None, step=None, index='0',
|
|
|
2062
2081
|
chip.logger.info(f'{suffix}: {line_with_num}')
|
|
2063
2082
|
|
|
2064
2083
|
for suffix in ordered_suffixes:
|
|
2065
|
-
chip.logger.info(f'Number of {suffix}: {matches[suffix]}')
|
|
2066
2084
|
checks[suffix]['report'].close()
|
|
2067
2085
|
|
|
2068
2086
|
return matches
|
|
@@ -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,8 +1,19 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
import shutil
|
|
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
|
|
3
7
|
from siliconcompiler.tools._common import \
|
|
4
8
|
add_frontend_requires, add_require_input, get_frontend_options, get_input_files, \
|
|
5
|
-
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)
|
|
6
17
|
|
|
7
18
|
|
|
8
19
|
def setup(chip):
|
|
@@ -10,13 +21,13 @@ def setup(chip):
|
|
|
10
21
|
Performs high level synthesis to generate a verilog output
|
|
11
22
|
'''
|
|
12
23
|
|
|
13
|
-
if not has_input_files(chip, 'input', 'hll', 'c')
|
|
14
|
-
|
|
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]"
|
|
15
27
|
|
|
16
|
-
tool = 'bambu'
|
|
17
28
|
step = chip.get('arg', 'step')
|
|
18
29
|
index = chip.get('arg', 'index')
|
|
19
|
-
|
|
30
|
+
tool, task = get_tool_task(chip, step, index)
|
|
20
31
|
|
|
21
32
|
# Standard Setup
|
|
22
33
|
refdir = 'tools/' + tool
|
|
@@ -27,24 +38,41 @@ def setup(chip):
|
|
|
27
38
|
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
28
39
|
step=step, index=index,
|
|
29
40
|
package='siliconcompiler', clobber=False)
|
|
30
|
-
chip.set('tool', tool, 'task', task, 'threads', os.cpu_count(),
|
|
31
|
-
step=step, index=index, clobber=False)
|
|
32
41
|
|
|
33
42
|
# Input/Output requirements
|
|
34
43
|
chip.add('tool', tool, 'task', task, 'output', chip.top() + '.v', step=step, index=index)
|
|
35
44
|
|
|
45
|
+
add_clock_requirements(chip)
|
|
46
|
+
|
|
36
47
|
# Schema requirements
|
|
37
48
|
add_require_input(chip, 'input', 'hll', 'c')
|
|
49
|
+
add_require_input(chip, 'input', 'hll', 'llvm')
|
|
38
50
|
add_frontend_requires(chip, ['idir', 'define'])
|
|
39
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
|
+
|
|
40
66
|
|
|
41
67
|
################################
|
|
42
68
|
# Custom runtime options
|
|
43
69
|
################################
|
|
44
70
|
def runtime_options(chip):
|
|
45
|
-
|
|
71
|
+
step = chip.get('arg', 'step')
|
|
72
|
+
index = chip.get('arg', 'index')
|
|
73
|
+
tool, task = get_tool_task(chip, step, index)
|
|
46
74
|
|
|
47
|
-
cmdlist
|
|
75
|
+
cmdlist = []
|
|
48
76
|
|
|
49
77
|
opts = get_frontend_options(chip, ['idir', 'define'])
|
|
50
78
|
|
|
@@ -54,11 +82,34 @@ def runtime_options(chip):
|
|
|
54
82
|
cmdlist.append('-D' + value)
|
|
55
83
|
for value in get_input_files(chip, 'input', 'hll', 'c'):
|
|
56
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)
|
|
57
89
|
|
|
90
|
+
cmdlist.append('--soft-float')
|
|
58
91
|
cmdlist.append('--memory-allocation-policy=NO_BRAM')
|
|
59
92
|
|
|
60
|
-
|
|
61
|
-
|
|
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]}')
|
|
62
113
|
|
|
63
114
|
cmdlist.append(f'--top-fname={chip.top(step, index)}')
|
|
64
115
|
|
|
@@ -75,3 +126,34 @@ def post_process(chip):
|
|
|
75
126
|
index = chip.get('arg', 'index')
|
|
76
127
|
|
|
77
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')
|
|
@@ -3,6 +3,7 @@ import shutil
|
|
|
3
3
|
from siliconcompiler.tools._common import \
|
|
4
4
|
add_require_input, add_frontend_requires, get_frontend_options, get_input_files, \
|
|
5
5
|
get_tool_task, has_input_files
|
|
6
|
+
from siliconcompiler import utils
|
|
6
7
|
from siliconcompiler import sc_open
|
|
7
8
|
|
|
8
9
|
# Directory inside step/index dir to store bsc intermediate results.
|
|
@@ -33,7 +34,7 @@ def setup(chip):
|
|
|
33
34
|
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
34
35
|
step=step, index=index,
|
|
35
36
|
package='siliconcompiler', clobber=False)
|
|
36
|
-
chip.set('tool', tool, 'task', task, 'threads',
|
|
37
|
+
chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
|
|
37
38
|
step=step, index=index, clobber=False)
|
|
38
39
|
|
|
39
40
|
# Input/Output requirements
|
|
@@ -3,6 +3,7 @@ import shutil
|
|
|
3
3
|
import glob
|
|
4
4
|
from siliconcompiler.tools._common import add_frontend_requires, get_tool_task, has_input_files
|
|
5
5
|
from siliconcompiler import sc_open, SiliconCompilerError
|
|
6
|
+
from siliconcompiler import utils
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def setup(chip):
|
|
@@ -28,7 +29,7 @@ def setup(chip):
|
|
|
28
29
|
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
29
30
|
step=step, index=index,
|
|
30
31
|
package='siliconcompiler', clobber=False)
|
|
31
|
-
chip.set('tool', tool, 'task', task, 'threads',
|
|
32
|
+
chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
|
|
32
33
|
step=step, index=index, clobber=False)
|
|
33
34
|
|
|
34
35
|
chip.set('tool', tool, 'task', task, 'option', ['-batch',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import shutil
|
|
2
|
+
from siliconcompiler import utils
|
|
3
3
|
from siliconcompiler.tools.genfasm import genfasm
|
|
4
4
|
from siliconcompiler.tools.vpr import vpr
|
|
5
5
|
from siliconcompiler.tools._common import get_tool_task
|
|
@@ -15,7 +15,7 @@ def setup(chip):
|
|
|
15
15
|
index = chip.get('arg', 'index')
|
|
16
16
|
tool, task = get_tool_task(chip, step, index)
|
|
17
17
|
|
|
18
|
-
chip.set('tool', tool, 'task', task, 'threads',
|
|
18
|
+
chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
|
|
19
19
|
step=step, index=index, clobber=False)
|
|
20
20
|
|
|
21
21
|
chip.set('tool', tool, 'task', task, 'regex', 'warnings', "^Warning",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from siliconcompiler.tools._common import add_require_input, add_frontend_requires, \
|
|
3
2
|
get_input_files, get_tool_task, has_input_files
|
|
3
|
+
from siliconcompiler import utils
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def setup(chip):
|
|
@@ -23,7 +23,7 @@ def setup(chip):
|
|
|
23
23
|
chip.set('tool', tool, 'vswitch', '--version')
|
|
24
24
|
chip.set('tool', tool, 'version', '>=4.0.0-dev', clobber=clobber)
|
|
25
25
|
|
|
26
|
-
chip.set('tool', tool, 'task', task, 'threads',
|
|
26
|
+
chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
|
|
27
27
|
step=step, index=index, clobber=clobber)
|
|
28
28
|
chip.set('tool', tool, 'task', task, 'option', '',
|
|
29
29
|
step=step, index=index, clobber=clobber)
|