siliconcompiler 0.30.0__py3-none-any.whl → 0.31.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_install.py +7 -3
- siliconcompiler/apps/sc_remote.py +1 -3
- siliconcompiler/core.py +23 -8
- siliconcompiler/flowgraph.py +11 -23
- siliconcompiler/package.py +1 -1
- siliconcompiler/remote/schema.py +9 -8
- siliconcompiler/report/report.py +4 -3
- siliconcompiler/scheduler/__init__.py +109 -104
- siliconcompiler/scheduler/docker_runner.py +1 -1
- siliconcompiler/scheduler/send_messages.py +1 -1
- siliconcompiler/schema/schema_cfg.py +367 -357
- siliconcompiler/schema/schema_obj.py +32 -18
- siliconcompiler/schema/utils.py +19 -0
- siliconcompiler/sphinx_ext/schemagen.py +3 -1
- siliconcompiler/templates/replay/replay.sh.j2 +92 -0
- siliconcompiler/tools/_common/__init__.py +8 -2
- siliconcompiler/tools/_common/asic.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/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_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/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 +14 -2
- 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.0.dist-info}/METADATA +7 -7
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/RECORD +69 -58
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/WHEEL +1 -1
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/LICENSE +0 -0
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.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:
|
|
@@ -1081,12 +1095,12 @@ class Schema:
|
|
|
1081
1095
|
typestr = self.get(*key, field='type')
|
|
1082
1096
|
pernode = self.get(*key, field='pernode')
|
|
1083
1097
|
|
|
1084
|
-
if pernode ==
|
|
1098
|
+
if PerNode(pernode) == PerNode.REQUIRED and (step is None or index is None):
|
|
1085
1099
|
# Skip mandatory per-node parameters if step and index are not specified
|
|
1086
1100
|
# TODO: how should we dump these?
|
|
1087
1101
|
continue
|
|
1088
1102
|
|
|
1089
|
-
if pernode
|
|
1103
|
+
if not pernode.is_never():
|
|
1090
1104
|
value = self.get(*key, step=step, index=index)
|
|
1091
1105
|
else:
|
|
1092
1106
|
value = self.get(*key)
|
|
@@ -1515,7 +1529,7 @@ class Schema:
|
|
|
1515
1529
|
used_switches.update(switchstrs)
|
|
1516
1530
|
if typestr == 'bool':
|
|
1517
1531
|
# Boolean type arguments
|
|
1518
|
-
if pernodestr
|
|
1532
|
+
if pernodestr.is_never():
|
|
1519
1533
|
parser.add_argument(*switchstrs,
|
|
1520
1534
|
nargs='?',
|
|
1521
1535
|
metavar=metavar,
|
|
@@ -1531,7 +1545,7 @@ class Schema:
|
|
|
1531
1545
|
action='append',
|
|
1532
1546
|
help=helpstr,
|
|
1533
1547
|
default=argparse.SUPPRESS)
|
|
1534
|
-
elif '[' in typestr or pernodestr
|
|
1548
|
+
elif '[' in typestr or not pernodestr.is_never():
|
|
1535
1549
|
# list type arguments
|
|
1536
1550
|
parser.add_argument(*switchstrs,
|
|
1537
1551
|
metavar=metavar,
|
|
@@ -1683,13 +1697,13 @@ class Schema:
|
|
|
1683
1697
|
sctype = self.get(*keypath, field='type')
|
|
1684
1698
|
pernode = self.get(*keypath, field='pernode')
|
|
1685
1699
|
step, index = None, None
|
|
1686
|
-
if pernode ==
|
|
1700
|
+
if PerNode(pernode) == PerNode.REQUIRED:
|
|
1687
1701
|
try:
|
|
1688
1702
|
step, index, val = remainder.split(' ', 2)
|
|
1689
1703
|
except ValueError:
|
|
1690
1704
|
self.logger.error(f"Invalid value '{item}' for switch {switchstr}. "
|
|
1691
1705
|
"Requires step and index before final value.")
|
|
1692
|
-
elif pernode ==
|
|
1706
|
+
elif PerNode(pernode) == PerNode.OPTIONAL:
|
|
1693
1707
|
# Split on spaces, preserving items that are grouped in quotes
|
|
1694
1708
|
items = shlex.split(remainder)
|
|
1695
1709
|
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():
|
|
@@ -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"]:
|
|
@@ -52,6 +52,14 @@ def setup(chip):
|
|
|
52
52
|
'clock_trees'
|
|
53
53
|
])
|
|
54
54
|
|
|
55
|
+
chip.set('tool', tool, 'task', task, 'var', 'drt_end_iteration',
|
|
56
|
+
'end iteration for detail routing',
|
|
57
|
+
field='help')
|
|
58
|
+
if chip.get('tool', tool, 'task', task, 'var', 'drt_end_iteration', step=step, index=index):
|
|
59
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
60
|
+
','.join(['tool', tool, 'task', task, 'var', 'drt_end_iteration']),
|
|
61
|
+
step=step, index=index)
|
|
62
|
+
|
|
55
63
|
|
|
56
64
|
def pre_process(chip):
|
|
57
65
|
define_ord_files(chip)
|
|
@@ -65,6 +65,12 @@ sc_set_dont_use
|
|
|
65
65
|
|
|
66
66
|
sc_setup_global_routing
|
|
67
67
|
|
|
68
|
+
# Store incoming markers to avoid rewriting them
|
|
69
|
+
set sc_starting_markers []
|
|
70
|
+
foreach markerdb [[ord::get_db_block] getMarkerCategories] {
|
|
71
|
+
lappend sc_starting_markers [$markerdb getName]
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
###############################
|
|
69
75
|
# Source Step Script
|
|
70
76
|
###############################
|