siliconcompiler 0.30.0__py3-none-any.whl → 0.31.1__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 +26 -4
- siliconcompiler/apps/sc_remote.py +1 -3
- siliconcompiler/core.py +24 -9
- siliconcompiler/flowgraph.py +11 -23
- siliconcompiler/{package.py → package/__init__.py} +62 -176
- siliconcompiler/package/git.py +81 -0
- siliconcompiler/package/https.py +93 -0
- siliconcompiler/remote/schema.py +9 -8
- siliconcompiler/report/report.py +4 -3
- siliconcompiler/scheduler/__init__.py +127 -113
- siliconcompiler/scheduler/docker_runner.py +4 -4
- siliconcompiler/scheduler/run_node.py +3 -3
- siliconcompiler/scheduler/send_messages.py +1 -1
- siliconcompiler/schema/schema_cfg.py +367 -357
- siliconcompiler/schema/schema_obj.py +39 -29
- siliconcompiler/schema/utils.py +19 -0
- siliconcompiler/sphinx_ext/schemagen.py +3 -1
- siliconcompiler/templates/replay/replay.sh.j2 +92 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +1 -1
- siliconcompiler/tools/_common/__init__.py +8 -2
- siliconcompiler/tools/_common/asic.py +1 -1
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +3 -5
- siliconcompiler/tools/genfasm/genfasm.py +1 -1
- siliconcompiler/tools/klayout/export.py +5 -0
- siliconcompiler/tools/klayout/klayout.py +18 -1
- siliconcompiler/tools/klayout/klayout_export.py +4 -1
- siliconcompiler/tools/klayout/klayout_operations.py +5 -2
- siliconcompiler/tools/klayout/klayout_utils.py +23 -0
- siliconcompiler/tools/klayout/operations.py +5 -0
- siliconcompiler/tools/magic/magic.py +1 -1
- siliconcompiler/tools/openroad/_apr.py +14 -3
- siliconcompiler/tools/openroad/antenna_repair.py +2 -1
- siliconcompiler/tools/openroad/clock_tree_synthesis.py +2 -1
- siliconcompiler/tools/openroad/detailed_placement.py +2 -1
- siliconcompiler/tools/openroad/detailed_route.py +8 -0
- siliconcompiler/tools/openroad/fillercell_insertion.py +2 -1
- siliconcompiler/tools/openroad/global_placement.py +2 -1
- siliconcompiler/tools/openroad/pin_placement.py +2 -1
- siliconcompiler/tools/openroad/rdlroute.py +4 -0
- siliconcompiler/tools/openroad/repair_design.py +2 -1
- siliconcompiler/tools/openroad/repair_timing.py +2 -1
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +6 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +8 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +3 -3
- siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +5 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +3 -0
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +29 -12
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +15 -0
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -0
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -13
- siliconcompiler/tools/vpr/vpr.py +86 -6
- siliconcompiler/tools/yosys/__init__.py +7 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +33 -24
- siliconcompiler/tools/yosys/syn_asic.py +27 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +27 -0
- siliconcompiler/toolscripts/_tools.json +15 -3
- siliconcompiler/toolscripts/rhel8/install-yosys-moosic.sh +17 -0
- siliconcompiler/toolscripts/rhel8/install-yosys-slang.sh +22 -0
- siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +17 -0
- siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +22 -0
- siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +17 -0
- siliconcompiler/toolscripts/ubuntu20/install-yosys-slang.sh +22 -0
- siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +17 -0
- siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +22 -0
- siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +17 -0
- siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +22 -0
- siliconcompiler/utils/__init__.py +33 -5
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/METADATA +21 -23
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/RECORD +79 -66
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/entry_points.txt +4 -0
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.1.dist-info}/top_level.txt +0 -0
|
@@ -39,7 +39,7 @@ except ImportError:
|
|
|
39
39
|
_has_yaml = False
|
|
40
40
|
|
|
41
41
|
from .schema_cfg import schema_cfg
|
|
42
|
-
from .utils import escape_val_tcl, PACKAGE_ROOT, translate_loglevel
|
|
42
|
+
from .utils import escape_val_tcl, PACKAGE_ROOT, translate_loglevel, PerNode, Scope
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class Schema:
|
|
@@ -287,7 +287,7 @@ class Schema:
|
|
|
287
287
|
try:
|
|
288
288
|
return cfg['node'][step][index][field]
|
|
289
289
|
except KeyError:
|
|
290
|
-
if cfg['pernode'] ==
|
|
290
|
+
if PerNode(cfg['pernode']) == PerNode.REQUIRED:
|
|
291
291
|
return cfg['node']['default']['default'][field]
|
|
292
292
|
|
|
293
293
|
try:
|
|
@@ -300,6 +300,10 @@ class Schema:
|
|
|
300
300
|
except KeyError:
|
|
301
301
|
return cfg['node']['default']['default'][field]
|
|
302
302
|
elif field in cfg:
|
|
303
|
+
if field == "pernode":
|
|
304
|
+
return PerNode(cfg[field])
|
|
305
|
+
if field == "scope":
|
|
306
|
+
return Scope(cfg[field])
|
|
303
307
|
return cfg[field]
|
|
304
308
|
else:
|
|
305
309
|
raise ValueError(f'Invalid field {field}')
|
|
@@ -621,7 +625,7 @@ class Schema:
|
|
|
621
625
|
has_global = True
|
|
622
626
|
vals.append((cfg['node'][step][index]['value'], step_arg, index_arg))
|
|
623
627
|
|
|
624
|
-
if (cfg['pernode'] !=
|
|
628
|
+
if (PerNode(cfg['pernode']) != PerNode.REQUIRED) and not has_global and return_defvalue:
|
|
625
629
|
vals.append((cfg['node']['default']['default']['value'], None, None))
|
|
626
630
|
|
|
627
631
|
return vals
|
|
@@ -707,7 +711,7 @@ class Schema:
|
|
|
707
711
|
# ignore history in case of cumulative history
|
|
708
712
|
if key[0] != 'history':
|
|
709
713
|
scope = self.get(*key, field='scope')
|
|
710
|
-
if not self.is_empty(*key) and (scope ==
|
|
714
|
+
if not self.is_empty(*key) and (scope == Scope.JOB):
|
|
711
715
|
self.__copyparam(self.cfg,
|
|
712
716
|
self.cfg['history'][jobname],
|
|
713
717
|
key)
|
|
@@ -865,15 +869,21 @@ class Schema:
|
|
|
865
869
|
|
|
866
870
|
if field == 'scope':
|
|
867
871
|
# Restricted allowed values
|
|
868
|
-
if
|
|
869
|
-
|
|
872
|
+
if isinstance(value, Scope):
|
|
873
|
+
return value.value
|
|
874
|
+
scope_values = [val.value for val in Scope]
|
|
875
|
+
if not (isinstance(value, str) and value in scope_values):
|
|
876
|
+
raise TypeError(error_msg(f'one of {", ".join(sorted(scope_values))}'))
|
|
870
877
|
return value
|
|
871
878
|
|
|
872
879
|
if field == 'pernode':
|
|
873
880
|
# Restricted allowed values
|
|
874
|
-
if
|
|
881
|
+
if isinstance(value, PerNode):
|
|
882
|
+
return value.value
|
|
883
|
+
pernode_values = [val.value for val in PerNode]
|
|
884
|
+
if not (isinstance(value, str) and value in pernode_values):
|
|
875
885
|
raise TypeError(f'Invalid value {value} for field {field}: '
|
|
876
|
-
'expected one of "
|
|
886
|
+
f'expected one of {", ".join(sorted(pernode_values))}')
|
|
877
887
|
return value
|
|
878
888
|
|
|
879
889
|
if field in (
|
|
@@ -955,10 +965,10 @@ class Schema:
|
|
|
955
965
|
return 'step and index are only valid for value fields'
|
|
956
966
|
return None
|
|
957
967
|
|
|
958
|
-
if pernode ==
|
|
968
|
+
if PerNode(pernode) == PerNode.NEVER and (step is not None or index is not None):
|
|
959
969
|
return 'step and index are not valid for this parameter'
|
|
960
970
|
|
|
961
|
-
if pernode ==
|
|
971
|
+
if PerNode(pernode) == PerNode.REQUIRED and (step is None or index is None):
|
|
962
972
|
return 'step and index are required for this parameter'
|
|
963
973
|
|
|
964
974
|
if step is None and index is not None:
|
|
@@ -989,11 +999,15 @@ class Schema:
|
|
|
989
999
|
if key in cfg:
|
|
990
1000
|
cfg = cfg[key]
|
|
991
1001
|
elif 'default' in cfg:
|
|
1002
|
+
cfg_default = cfg['default']
|
|
992
1003
|
if insert_defaults:
|
|
993
|
-
|
|
1004
|
+
if Schema._is_leaf(cfg_default) and cfg_default['lock']:
|
|
1005
|
+
raise ValueError(f'{keypath} is locked and key cannot be added')
|
|
1006
|
+
|
|
1007
|
+
cfg[key] = copy.deepcopy(cfg_default)
|
|
994
1008
|
cfg = cfg[key]
|
|
995
1009
|
elif use_default:
|
|
996
|
-
cfg =
|
|
1010
|
+
cfg = cfg_default
|
|
997
1011
|
else:
|
|
998
1012
|
raise ValueError(f'Invalid keypath {keypath}: unexpected key: {key}')
|
|
999
1013
|
else:
|
|
@@ -1078,15 +1092,19 @@ class Schema:
|
|
|
1078
1092
|
|
|
1079
1093
|
tcl_set_cmds = []
|
|
1080
1094
|
for key in self.allkeys():
|
|
1095
|
+
# print out all non default values
|
|
1096
|
+
if 'default' in key:
|
|
1097
|
+
continue
|
|
1098
|
+
|
|
1081
1099
|
typestr = self.get(*key, field='type')
|
|
1082
1100
|
pernode = self.get(*key, field='pernode')
|
|
1083
1101
|
|
|
1084
|
-
if pernode ==
|
|
1102
|
+
if PerNode(pernode) == PerNode.REQUIRED and (step is None or index is None):
|
|
1085
1103
|
# Skip mandatory per-node parameters if step and index are not specified
|
|
1086
1104
|
# TODO: how should we dump these?
|
|
1087
1105
|
continue
|
|
1088
1106
|
|
|
1089
|
-
if pernode
|
|
1107
|
+
if not pernode.is_never():
|
|
1090
1108
|
value = self.get(*key, step=step, index=index)
|
|
1091
1109
|
else:
|
|
1092
1110
|
value = self.get(*key)
|
|
@@ -1096,19 +1114,11 @@ class Schema:
|
|
|
1096
1114
|
|
|
1097
1115
|
valstr = escape_val_tcl(value, typestr)
|
|
1098
1116
|
|
|
1099
|
-
#
|
|
1100
|
-
if not (typestr.startswith('[') or typestr.startswith('(')):
|
|
1101
|
-
valstr = f'[list {valstr}]'
|
|
1102
|
-
|
|
1103
|
-
# TODO: Temp fix to get rid of empty args
|
|
1117
|
+
# Ensure empty values get something
|
|
1104
1118
|
if valstr == '':
|
|
1105
|
-
valstr = '
|
|
1106
|
-
|
|
1107
|
-
outstr = f"{prefix} {keystr} {valstr}"
|
|
1119
|
+
valstr = '{}'
|
|
1108
1120
|
|
|
1109
|
-
|
|
1110
|
-
if 'default' not in key:
|
|
1111
|
-
tcl_set_cmds.append(outstr)
|
|
1121
|
+
tcl_set_cmds.append(f"{prefix} {keystr} {valstr}")
|
|
1112
1122
|
|
|
1113
1123
|
if template:
|
|
1114
1124
|
fout.write(template.render(manifest_dict='\n'.join(tcl_set_cmds),
|
|
@@ -1515,7 +1525,7 @@ class Schema:
|
|
|
1515
1525
|
used_switches.update(switchstrs)
|
|
1516
1526
|
if typestr == 'bool':
|
|
1517
1527
|
# Boolean type arguments
|
|
1518
|
-
if pernodestr
|
|
1528
|
+
if pernodestr.is_never():
|
|
1519
1529
|
parser.add_argument(*switchstrs,
|
|
1520
1530
|
nargs='?',
|
|
1521
1531
|
metavar=metavar,
|
|
@@ -1531,7 +1541,7 @@ class Schema:
|
|
|
1531
1541
|
action='append',
|
|
1532
1542
|
help=helpstr,
|
|
1533
1543
|
default=argparse.SUPPRESS)
|
|
1534
|
-
elif '[' in typestr or pernodestr
|
|
1544
|
+
elif '[' in typestr or not pernodestr.is_never():
|
|
1535
1545
|
# list type arguments
|
|
1536
1546
|
parser.add_argument(*switchstrs,
|
|
1537
1547
|
metavar=metavar,
|
|
@@ -1683,13 +1693,13 @@ class Schema:
|
|
|
1683
1693
|
sctype = self.get(*keypath, field='type')
|
|
1684
1694
|
pernode = self.get(*keypath, field='pernode')
|
|
1685
1695
|
step, index = None, None
|
|
1686
|
-
if pernode ==
|
|
1696
|
+
if PerNode(pernode) == PerNode.REQUIRED:
|
|
1687
1697
|
try:
|
|
1688
1698
|
step, index, val = remainder.split(' ', 2)
|
|
1689
1699
|
except ValueError:
|
|
1690
1700
|
self.logger.error(f"Invalid value '{item}' for switch {switchstr}. "
|
|
1691
1701
|
"Requires step and index before final value.")
|
|
1692
|
-
elif pernode ==
|
|
1702
|
+
elif PerNode(pernode) == PerNode.OPTIONAL:
|
|
1693
1703
|
# Split on spaces, preserving items that are grouped in quotes
|
|
1694
1704
|
items = shlex.split(remainder)
|
|
1695
1705
|
if len(items) > 3:
|
siliconcompiler/schema/utils.py
CHANGED
|
@@ -7,10 +7,29 @@
|
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
9
|
import sys
|
|
10
|
+
from enum import Enum
|
|
10
11
|
|
|
11
12
|
PACKAGE_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
#############################################################################
|
|
16
|
+
# ENUM DEFINITIONs
|
|
17
|
+
#############################################################################
|
|
18
|
+
class Scope(Enum):
|
|
19
|
+
GLOBAL = 'global'
|
|
20
|
+
JOB = 'job'
|
|
21
|
+
SCRATCH = 'scratch'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PerNode(Enum):
|
|
25
|
+
NEVER = 'never'
|
|
26
|
+
OPTIONAL = 'optional'
|
|
27
|
+
REQUIRED = 'required'
|
|
28
|
+
|
|
29
|
+
def is_never(self):
|
|
30
|
+
return self == PerNode.NEVER
|
|
31
|
+
|
|
32
|
+
|
|
14
33
|
def escape_val_tcl(val, typestr):
|
|
15
34
|
'''Recursive helper function for converting Python values to safe TCL
|
|
16
35
|
values, based on the SC type string.'''
|
|
@@ -37,9 +37,11 @@ class SchemaGen(SphinxDirective):
|
|
|
37
37
|
entries = [[strong('Description'), para(schema['shorthelp'])],
|
|
38
38
|
[strong('Type'), para(schema['type'])]]
|
|
39
39
|
|
|
40
|
-
if schema['pernode'] !=
|
|
40
|
+
if schema['pernode'] != utils.PerNode.NEVER:
|
|
41
41
|
entries.append([strong('Per step/index'), para(schema['pernode'])])
|
|
42
42
|
|
|
43
|
+
entries.append([strong('Scope'), para(schema['scope'])])
|
|
44
|
+
|
|
43
45
|
if 'enum' in schema['type']:
|
|
44
46
|
entries.append([strong('Allowed Values'),
|
|
45
47
|
build_list([code(val) for val in schema['enum']])])
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
if [ "${BASH_SOURCE[0]}" != "$0" ]; then
|
|
3
|
+
echo "${BASH_SOURCE[0]} must be executed."
|
|
4
|
+
return
|
|
5
|
+
fi
|
|
6
|
+
|
|
7
|
+
# Parse replay arguments
|
|
8
|
+
CD_WORK="{{ work_dir }}"
|
|
9
|
+
PRINT=""
|
|
10
|
+
CMDPREFIX=""
|
|
11
|
+
SKIPEXPORT=0
|
|
12
|
+
while [[ $# -gt 0 ]]; do
|
|
13
|
+
case $1 in
|
|
14
|
+
--which)
|
|
15
|
+
PRINT="which"
|
|
16
|
+
shift
|
|
17
|
+
;;
|
|
18
|
+
--version)
|
|
19
|
+
PRINT="version"
|
|
20
|
+
shift
|
|
21
|
+
;;
|
|
22
|
+
--directory)
|
|
23
|
+
PRINT="directory"
|
|
24
|
+
shift
|
|
25
|
+
;;
|
|
26
|
+
--command)
|
|
27
|
+
PRINT="command"
|
|
28
|
+
shift
|
|
29
|
+
;;
|
|
30
|
+
--skipcd)
|
|
31
|
+
CD_WORK="."
|
|
32
|
+
shift
|
|
33
|
+
;;
|
|
34
|
+
--skipexports)
|
|
35
|
+
SKIPEXPORT=1
|
|
36
|
+
shift
|
|
37
|
+
;;
|
|
38
|
+
--cmdprefix)
|
|
39
|
+
CMDPREFIX="$2"
|
|
40
|
+
shift
|
|
41
|
+
shift
|
|
42
|
+
;;
|
|
43
|
+
-h|--help)
|
|
44
|
+
echo "Usage: $0"
|
|
45
|
+
echo " Options:"
|
|
46
|
+
echo " --which print which executable would be used"
|
|
47
|
+
echo " --version print the version of the executable, if supported"
|
|
48
|
+
echo " --directory print the execution directory"
|
|
49
|
+
echo " --command print the execution command"
|
|
50
|
+
echo " --skipcd do not change directory into replay directory"
|
|
51
|
+
echo " --skipexports do not export environmental variables"
|
|
52
|
+
echo " --cmdprefix <cmd> prefix to add to the replay command, such as gdb"
|
|
53
|
+
echo " -h,--help print this help"
|
|
54
|
+
exit 0
|
|
55
|
+
;;
|
|
56
|
+
*)
|
|
57
|
+
echo "Unknown option $1"
|
|
58
|
+
exit 1
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
if [ $SKIPEXPORT == 0 ]; then
|
|
64
|
+
# Environmental variables{% for key, value in exports.items() %}
|
|
65
|
+
export {{ key }}="{{ value }}"{% endfor %}
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Switch to the working directory
|
|
69
|
+
cd "$CD_WORK"
|
|
70
|
+
|
|
71
|
+
case $PRINT in
|
|
72
|
+
"which")
|
|
73
|
+
which {{ executable }}
|
|
74
|
+
exit 0
|
|
75
|
+
;;
|
|
76
|
+
"version")
|
|
77
|
+
{% if version_flag is defined %}{{ executable }} {{ version_flag }}{% else %}echo "--version is not supported"{% endif %}
|
|
78
|
+
exit 0
|
|
79
|
+
;;
|
|
80
|
+
"directory")
|
|
81
|
+
echo "Working directory: $PWD"
|
|
82
|
+
exit 0
|
|
83
|
+
;;
|
|
84
|
+
"command")
|
|
85
|
+
echo "{% for cmd in cmds %}{% if not loop.first %} {% endif %}{{ cmd }}{% endfor %}"
|
|
86
|
+
exit 0
|
|
87
|
+
;;
|
|
88
|
+
esac
|
|
89
|
+
|
|
90
|
+
# Command execution
|
|
91
|
+
$CMDPREFIX \{% for cmd in cmds %}
|
|
92
|
+
{% if not loop.first %} {% endif %}{{ cmd }}{% if not loop.last %} \{% endif %}{% endfor %}
|
|
@@ -161,7 +161,7 @@ def __get_step_index(chip, *key):
|
|
|
161
161
|
step = chip.get('arg', 'step')
|
|
162
162
|
index = chip.get('arg', 'index')
|
|
163
163
|
|
|
164
|
-
if chip.get(*key, field='pernode')
|
|
164
|
+
if chip.get(*key, field='pernode').is_never():
|
|
165
165
|
step = None
|
|
166
166
|
index = None
|
|
167
167
|
|
|
@@ -330,7 +330,7 @@ def pick_key(chip, check_keys, step=None, index=None):
|
|
|
330
330
|
check_step = step
|
|
331
331
|
check_index = index
|
|
332
332
|
|
|
333
|
-
if chip.get(*key, field='pernode')
|
|
333
|
+
if chip.get(*key, field='pernode').is_never():
|
|
334
334
|
check_step = None
|
|
335
335
|
check_index = None
|
|
336
336
|
|
|
@@ -347,9 +347,15 @@ def input_provides(chip, step, index, flow=None):
|
|
|
347
347
|
if not flow:
|
|
348
348
|
flow = chip.get('option', 'flow')
|
|
349
349
|
|
|
350
|
+
pruned_nodes = chip.get('option', 'prune')
|
|
351
|
+
|
|
350
352
|
nodes = chip.get('flowgraph', flow, step, index, 'input')
|
|
351
353
|
inputs = {}
|
|
352
354
|
for in_step, in_index in nodes:
|
|
355
|
+
if (in_step, in_index) in pruned_nodes:
|
|
356
|
+
# node has been pruned so will not provide anything
|
|
357
|
+
continue
|
|
358
|
+
|
|
353
359
|
if chip.get('record', 'status', step=in_step, index=in_index) == \
|
|
354
360
|
NodeStatus.SKIPPED:
|
|
355
361
|
for file, nodes in input_provides(chip, in_step, in_index, flow=flow).items():
|
|
@@ -15,22 +15,20 @@ proc sc_collect_pin_constraints {
|
|
|
15
15
|
set side [dict get $params side]
|
|
16
16
|
set place [dict get $params placement]
|
|
17
17
|
|
|
18
|
-
if {
|
|
18
|
+
if { $place != {} } {
|
|
19
19
|
# Pin has placement information
|
|
20
|
-
if {
|
|
20
|
+
if { $order != {} } {
|
|
21
21
|
# Pin also has order information
|
|
22
22
|
$print_func "Pin $name has placement specified in constraints, but also order."
|
|
23
23
|
}
|
|
24
24
|
lappend placement_pins $name
|
|
25
25
|
} else {
|
|
26
26
|
# Pin doesn't have placement
|
|
27
|
-
if {
|
|
27
|
+
if { $side == {} || $order == {} } {
|
|
28
28
|
# Pin information is incomplete
|
|
29
29
|
$print_func \
|
|
30
30
|
"Warning: Pin $name doesn't have enough information to perform placement."
|
|
31
31
|
} else {
|
|
32
|
-
set side [lindex $side 0]
|
|
33
|
-
set order [lindex $order 0]
|
|
34
32
|
if { ![dict exists $pin_order $side $order] } {
|
|
35
33
|
dict set pin_order $side $order []
|
|
36
34
|
}
|
|
@@ -24,7 +24,7 @@ def make_docs(chip):
|
|
|
24
24
|
def setup(chip):
|
|
25
25
|
chip.set('tool', 'genfasm', 'exe', 'genfasm', clobber=False)
|
|
26
26
|
chip.set('tool', 'genfasm', 'vswitch', '--version')
|
|
27
|
-
chip.set('tool', 'genfasm', 'version', '>=
|
|
27
|
+
chip.set('tool', 'genfasm', 'version', '>=9.0.0', clobber=False)
|
|
28
28
|
|
|
29
29
|
add_tool_requirements(chip)
|
|
30
30
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from siliconcompiler.tools.klayout.klayout import setup as setup_tool
|
|
3
|
+
from siliconcompiler.tools.klayout.klayout import process_metrics
|
|
3
4
|
from siliconcompiler.tools.klayout.klayout import runtime_options as runtime_options_tool
|
|
4
5
|
from siliconcompiler.tools.klayout.screenshot import setup_gui_screenshot
|
|
5
6
|
from siliconcompiler.tools._common import input_provides, get_tool_task
|
|
@@ -127,3 +128,7 @@ def runtime_options(chip):
|
|
|
127
128
|
return runtime_options_tool(chip) + [
|
|
128
129
|
'-rd', f'SC_TOOLS_ROOT={os.path.dirname(os.path.dirname(__file__))}'
|
|
129
130
|
]
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def post_process(chip):
|
|
134
|
+
process_metrics(chip)
|
|
@@ -12,9 +12,11 @@ Installation: https://www.klayout.de/build.html
|
|
|
12
12
|
|
|
13
13
|
import os
|
|
14
14
|
from pathlib import Path
|
|
15
|
+
import json
|
|
15
16
|
import platform
|
|
16
17
|
import shutil
|
|
17
|
-
from siliconcompiler.tools._common import get_tool_task
|
|
18
|
+
from siliconcompiler.tools._common import get_tool_task, record_metric
|
|
19
|
+
from siliconcompiler import sc_open
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
####################################################################
|
|
@@ -113,6 +115,21 @@ def parse_version(stdout):
|
|
|
113
115
|
return stdout.split()[1]
|
|
114
116
|
|
|
115
117
|
|
|
118
|
+
def process_metrics(chip):
|
|
119
|
+
metrics_file = "reports/metrics.json"
|
|
120
|
+
if not os.path.exists(metrics_file):
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
step = chip.get('arg', 'step')
|
|
124
|
+
index = chip.get('arg', 'index')
|
|
125
|
+
|
|
126
|
+
with sc_open(metrics_file) as f:
|
|
127
|
+
metrics = json.load(f)
|
|
128
|
+
|
|
129
|
+
if "area" in metrics:
|
|
130
|
+
record_metric(chip, step, index, "totalarea", metrics["area"], metrics_file, "um^2")
|
|
131
|
+
|
|
132
|
+
|
|
116
133
|
##################################################
|
|
117
134
|
if __name__ == "__main__":
|
|
118
135
|
|
|
@@ -127,7 +127,8 @@ def main():
|
|
|
127
127
|
technology,
|
|
128
128
|
get_streams,
|
|
129
129
|
save_technology,
|
|
130
|
-
get_schema
|
|
130
|
+
get_schema,
|
|
131
|
+
generate_metrics
|
|
131
132
|
)
|
|
132
133
|
from klayout_show import show
|
|
133
134
|
from _common.asic import get_libraries
|
|
@@ -205,6 +206,8 @@ def main():
|
|
|
205
206
|
# Save tech files
|
|
206
207
|
save_technology(design, sc_tech)
|
|
207
208
|
|
|
209
|
+
generate_metrics()
|
|
210
|
+
|
|
208
211
|
|
|
209
212
|
if __name__ == '__main__':
|
|
210
213
|
main()
|
|
@@ -25,7 +25,7 @@ def __get_keypath_step_index(schema, *keypath):
|
|
|
25
25
|
'index': schema.get('arg', 'index')
|
|
26
26
|
}
|
|
27
27
|
pernode = schema.get(*keypath, field='pernode')
|
|
28
|
-
if pernode
|
|
28
|
+
if pernode.is_never():
|
|
29
29
|
ret['step'] = None
|
|
30
30
|
ret['index'] = None
|
|
31
31
|
|
|
@@ -330,7 +330,8 @@ if __name__ == "__main__":
|
|
|
330
330
|
from klayout_utils import (
|
|
331
331
|
technology,
|
|
332
332
|
get_streams,
|
|
333
|
-
get_schema
|
|
333
|
+
get_schema,
|
|
334
|
+
generate_metrics
|
|
334
335
|
)
|
|
335
336
|
|
|
336
337
|
schema = get_schema(manifest='sc_manifest.json')
|
|
@@ -362,3 +363,5 @@ if __name__ == "__main__":
|
|
|
362
363
|
parse_operations(schema, base_layout, sc_klayout_ops)
|
|
363
364
|
|
|
364
365
|
write_stream(base_layout, out_gds, __with_timestamps(schema))
|
|
366
|
+
|
|
367
|
+
generate_metrics()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pya
|
|
2
2
|
import importlib.util as importlib_util
|
|
3
|
+
import json
|
|
3
4
|
import os
|
|
4
5
|
import shutil
|
|
5
6
|
import sys
|
|
@@ -180,3 +181,25 @@ def get_schema(manifest):
|
|
|
180
181
|
spec.loader.exec_module(module)
|
|
181
182
|
# Return schema
|
|
182
183
|
return module.Schema(manifest=manifest)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def generate_metrics():
|
|
187
|
+
metrics = {}
|
|
188
|
+
|
|
189
|
+
main_window = pya.MainWindow.instance()
|
|
190
|
+
if not main_window:
|
|
191
|
+
return
|
|
192
|
+
layout_view = main_window.current_view()
|
|
193
|
+
if not layout_view:
|
|
194
|
+
return
|
|
195
|
+
cell_view = layout_view.active_cellview()
|
|
196
|
+
if not cell_view:
|
|
197
|
+
return
|
|
198
|
+
cell = cell_view.cell
|
|
199
|
+
if not cell:
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
metrics["area"] = cell.dbbox().area()
|
|
203
|
+
|
|
204
|
+
with open('reports/metrics.json', 'w') as f:
|
|
205
|
+
json.dump(metrics, f, indent=2)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from siliconcompiler import SiliconCompilerError
|
|
3
3
|
from siliconcompiler.tools.klayout.klayout import setup as setup_tool
|
|
4
|
+
from siliconcompiler.tools.klayout.klayout import process_metrics
|
|
4
5
|
from siliconcompiler.tools.klayout.klayout import runtime_options as runtime_options_tool
|
|
5
6
|
from siliconcompiler.tools._common import input_provides, get_tool_task
|
|
6
7
|
|
|
@@ -202,3 +203,7 @@ def runtime_options(chip):
|
|
|
202
203
|
return runtime_options_tool(chip) + [
|
|
203
204
|
'-rd', f'SC_TOOLS_ROOT={os.path.dirname(os.path.dirname(__file__))}'
|
|
204
205
|
]
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def post_process(chip):
|
|
209
|
+
process_metrics(chip)
|
|
@@ -87,7 +87,7 @@ def process_file(file_type, chip, *key):
|
|
|
87
87
|
index = chip.get('arg', 'index')
|
|
88
88
|
tool, task = get_tool_task(chip, step, index)
|
|
89
89
|
|
|
90
|
-
if chip.get(*key, field='pernode')
|
|
90
|
+
if chip.get(*key, field='pernode').is_never():
|
|
91
91
|
files = chip.find_files(*key)
|
|
92
92
|
else:
|
|
93
93
|
files = chip.find_files(*key, step=step, index=index)
|
|
@@ -197,13 +197,15 @@ def extract_metrics(chip):
|
|
|
197
197
|
has_timing = metrics['sc__metric__timing__clocks'] > 0
|
|
198
198
|
|
|
199
199
|
for metric, or_metric, or_use, or_unit in [
|
|
200
|
+
('vias', 'sc__step__global_route__vias', True, None),
|
|
200
201
|
('vias', 'sc__step__route__vias', True, None),
|
|
202
|
+
('wirelength', 'sc__step__global_route__wirelength', True, 'distance'),
|
|
201
203
|
('wirelength', 'sc__step__route__wirelength', True, 'distance'),
|
|
202
204
|
('cellarea', 'sc__metric__design__instance__area', True, 'area'),
|
|
203
205
|
('stdcellarea', 'sc__metric__design__instance__area__stdcell', True, 'area'),
|
|
204
206
|
('macroarea', 'sc__metric__design__instance__area__macros', True, 'area'),
|
|
205
207
|
('padcellarea', 'sc__metric__design__instance__area__padcells', True, 'area'),
|
|
206
|
-
('totalarea', '
|
|
208
|
+
('totalarea', 'sc__metric__design__die__area', True, 'area'),
|
|
207
209
|
('utilization', 'sc__metric__design__instance__utilization', True, 100.0),
|
|
208
210
|
('setuptns', 'sc__metric__timing__setup__tns', has_timing, 'time'),
|
|
209
211
|
('holdtns', 'sc__metric__timing__hold__tns', has_timing, 'time'),
|
|
@@ -763,6 +765,10 @@ def define_drt_params(chip):
|
|
|
763
765
|
schelp='list of layers to treat as unidirectional regardless of '
|
|
764
766
|
'what the tech lef specifies')
|
|
765
767
|
|
|
768
|
+
set_tool_task_var(chip, param_key='drt_report_interval',
|
|
769
|
+
default_value=5,
|
|
770
|
+
schelp='reporting interval in steps for generating a DRC report.')
|
|
771
|
+
|
|
766
772
|
|
|
767
773
|
def define_sta_params(chip):
|
|
768
774
|
step = chip.get('arg', 'step')
|
|
@@ -868,6 +874,10 @@ def define_mpl_params(chip):
|
|
|
868
874
|
set_tool_task_var(chip, param_key='rtlmp_fence_weight',
|
|
869
875
|
schelp='Weight for fence cost, or how far the macro is from zero '
|
|
870
876
|
'fence violation')
|
|
877
|
+
set_tool_task_var(chip, param_key='rtlmp_boundary_weight',
|
|
878
|
+
schelp='Weight for the boundary, or how far the hard macro clusters are from '
|
|
879
|
+
'boundaries. Note that mixed macro clusters are not pushed, thus not '
|
|
880
|
+
'considered in this cost.')
|
|
871
881
|
set_tool_task_var(chip, param_key='rtlmp_blockage_weight',
|
|
872
882
|
schelp='Weight for the boundary, or how far the hard macro clusters are '
|
|
873
883
|
'from boundaries')
|
|
@@ -980,7 +990,8 @@ def set_reports(chip, reports):
|
|
|
980
990
|
"ir_drop",
|
|
981
991
|
"clock_placement",
|
|
982
992
|
"clock_trees",
|
|
983
|
-
"optimization_placement"
|
|
993
|
+
"optimization_placement",
|
|
994
|
+
"module_view"
|
|
984
995
|
)
|
|
985
996
|
|
|
986
997
|
chip.set('tool', tool, 'task', task, 'var', 'reports',
|
|
@@ -994,7 +1005,7 @@ def set_reports(chip, reports):
|
|
|
994
1005
|
for key in (('tool', tool, 'task', task, 'var', f'skip_{type}'),
|
|
995
1006
|
('option', 'var', f'openroad_skip_{type}')):
|
|
996
1007
|
if chip.valid(*key):
|
|
997
|
-
if chip.get(*key, field='pernode')
|
|
1008
|
+
if chip.get(*key, field='pernode').is_never():
|
|
998
1009
|
if chip.get(*key) == ["true"]:
|
|
999
1010
|
return False
|
|
1000
1011
|
elif chip.get(*key, step=step, index=index) == ["true"]:
|