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.
Files changed (69) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_install.py +7 -3
  3. siliconcompiler/apps/sc_remote.py +1 -3
  4. siliconcompiler/core.py +23 -8
  5. siliconcompiler/flowgraph.py +11 -23
  6. siliconcompiler/package.py +1 -1
  7. siliconcompiler/remote/schema.py +9 -8
  8. siliconcompiler/report/report.py +4 -3
  9. siliconcompiler/scheduler/__init__.py +109 -104
  10. siliconcompiler/scheduler/docker_runner.py +1 -1
  11. siliconcompiler/scheduler/send_messages.py +1 -1
  12. siliconcompiler/schema/schema_cfg.py +367 -357
  13. siliconcompiler/schema/schema_obj.py +32 -18
  14. siliconcompiler/schema/utils.py +19 -0
  15. siliconcompiler/sphinx_ext/schemagen.py +3 -1
  16. siliconcompiler/templates/replay/replay.sh.j2 +92 -0
  17. siliconcompiler/tools/_common/__init__.py +8 -2
  18. siliconcompiler/tools/_common/asic.py +1 -1
  19. siliconcompiler/tools/klayout/export.py +5 -0
  20. siliconcompiler/tools/klayout/klayout.py +18 -1
  21. siliconcompiler/tools/klayout/klayout_export.py +4 -1
  22. siliconcompiler/tools/klayout/klayout_operations.py +5 -2
  23. siliconcompiler/tools/klayout/klayout_utils.py +23 -0
  24. siliconcompiler/tools/klayout/operations.py +5 -0
  25. siliconcompiler/tools/magic/magic.py +1 -1
  26. siliconcompiler/tools/openroad/_apr.py +14 -3
  27. siliconcompiler/tools/openroad/antenna_repair.py +2 -1
  28. siliconcompiler/tools/openroad/clock_tree_synthesis.py +2 -1
  29. siliconcompiler/tools/openroad/detailed_placement.py +2 -1
  30. siliconcompiler/tools/openroad/detailed_route.py +8 -0
  31. siliconcompiler/tools/openroad/fillercell_insertion.py +2 -1
  32. siliconcompiler/tools/openroad/global_placement.py +2 -1
  33. siliconcompiler/tools/openroad/pin_placement.py +2 -1
  34. siliconcompiler/tools/openroad/repair_design.py +2 -1
  35. siliconcompiler/tools/openroad/repair_timing.py +2 -1
  36. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +6 -0
  37. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +1 -0
  38. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +8 -0
  39. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +1 -0
  40. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -0
  41. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +5 -0
  42. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +1 -0
  43. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -0
  44. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +3 -0
  45. siliconcompiler/tools/openroad/scripts/common/procs.tcl +29 -12
  46. siliconcompiler/tools/openroad/scripts/common/reports.tcl +15 -0
  47. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -0
  48. siliconcompiler/tools/yosys/__init__.py +7 -0
  49. siliconcompiler/tools/yosys/sc_syn.tcl +33 -24
  50. siliconcompiler/tools/yosys/syn_asic.py +27 -0
  51. siliconcompiler/tools/yosys/syn_asic.tcl +27 -0
  52. siliconcompiler/toolscripts/_tools.json +14 -2
  53. siliconcompiler/toolscripts/rhel8/install-yosys-moosic.sh +17 -0
  54. siliconcompiler/toolscripts/rhel8/install-yosys-slang.sh +22 -0
  55. siliconcompiler/toolscripts/rhel9/install-yosys-moosic.sh +17 -0
  56. siliconcompiler/toolscripts/rhel9/install-yosys-slang.sh +22 -0
  57. siliconcompiler/toolscripts/ubuntu20/install-yosys-moosic.sh +17 -0
  58. siliconcompiler/toolscripts/ubuntu20/install-yosys-slang.sh +22 -0
  59. siliconcompiler/toolscripts/ubuntu22/install-yosys-moosic.sh +17 -0
  60. siliconcompiler/toolscripts/ubuntu22/install-yosys-slang.sh +22 -0
  61. siliconcompiler/toolscripts/ubuntu24/install-yosys-moosic.sh +17 -0
  62. siliconcompiler/toolscripts/ubuntu24/install-yosys-slang.sh +22 -0
  63. siliconcompiler/utils/__init__.py +33 -5
  64. {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/METADATA +7 -7
  65. {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/RECORD +69 -58
  66. {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/WHEEL +1 -1
  67. {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/LICENSE +0 -0
  68. {siliconcompiler-0.30.0.dist-info → siliconcompiler-0.31.0.dist-info}/entry_points.txt +0 -0
  69. {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'] == 'required':
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'] != 'required') and not has_global and return_defvalue:
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 == 'job'):
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 not (isinstance(value, str) and value in ('global', 'job', 'scratch')):
869
- raise TypeError(error_msg('one of "global", "job", or "scratch"'))
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 not (isinstance(value, str) and value in ('never', 'optional', 'required')):
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 "never", "optional", or "required"')
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 == 'never' and (step is not None or index is not None):
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 == 'required' and (step is None or index is None):
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
- cfg[key] = copy.deepcopy(cfg['default'])
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 = cfg['default']
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 == 'required' and (step is None or index is None):
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 != 'never':
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 == 'never':
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 != 'never':
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 == 'required':
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 == 'optional':
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:
@@ -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'] != 'never':
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') == 'never':
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') == 'never':
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():
@@ -188,7 +188,7 @@ def set_tool_task_lib_var(chip,
188
188
  get_step = step
189
189
  get_index = index
190
190
 
191
- if chip.get(*lib_key, field='pernode') == 'never':
191
+ if chip.get(*lib_key, field='pernode').is_never():
192
192
  get_step = None
193
193
  get_index = None
194
194
 
@@ -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 == 'never':
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') == 'never':
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', 'sc__metric__design__core__area', True, 'area'),
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') == 'never':
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"]:
@@ -54,7 +54,8 @@ def setup(chip):
54
54
  'power_density',
55
55
  'optimization_placement',
56
56
  'clock_placement',
57
- 'clock_trees'
57
+ 'clock_trees',
58
+ 'module_view'
58
59
  ])
59
60
 
60
61
 
@@ -51,7 +51,8 @@ def setup(chip):
51
51
  'power_density',
52
52
  'optimization_placement',
53
53
  'clock_placement',
54
- 'clock_trees'
54
+ 'clock_trees',
55
+ 'module_view'
55
56
  ])
56
57
 
57
58
 
@@ -46,7 +46,8 @@ def setup(chip):
46
46
  'placement_density',
47
47
  'routing_congestion',
48
48
  'power_density',
49
- 'optimization_placement'
49
+ 'optimization_placement',
50
+ 'module_view'
50
51
  ])
51
52
 
52
53
 
@@ -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)
@@ -45,7 +45,8 @@ def setup(chip):
45
45
  # Images
46
46
  'placement_density',
47
47
  'routing_congestion',
48
- 'power_density'
48
+ 'power_density',
49
+ 'module_view'
49
50
  ])
50
51
 
51
52
 
@@ -48,7 +48,8 @@ def setup(chip):
48
48
  # Images
49
49
  'placement_density',
50
50
  'routing_congestion',
51
- 'power_density'
51
+ 'power_density',
52
+ 'module_view'
52
53
  ])
53
54
 
54
55
  set_tool_task_var(chip, param_key='enable_multibit_clustering',
@@ -42,7 +42,8 @@ def setup(chip):
42
42
  # Images
43
43
  'placement_density',
44
44
  'routing_congestion',
45
- 'power_density'
45
+ 'power_density',
46
+ 'module_view'
46
47
  ])
47
48
 
48
49
 
@@ -46,7 +46,8 @@ def setup(chip):
46
46
  'placement_density',
47
47
  'routing_congestion',
48
48
  'power_density',
49
- 'optimization_placement'
49
+ 'optimization_placement',
50
+ 'module_view'
50
51
  ])
51
52
 
52
53
 
@@ -50,7 +50,8 @@ def setup(chip):
50
50
  'power_density',
51
51
  'optimization_placement',
52
52
  'clock_placement',
53
- 'clock_trees'
53
+ 'clock_trees',
54
+ 'module_view'
54
55
  ])
55
56
 
56
57
 
@@ -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
  ###############################