siliconcompiler 0.29.3__py3-none-any.whl → 0.29.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_install.py +18 -3
  3. siliconcompiler/remote/client.py +3 -0
  4. siliconcompiler/scheduler/__init__.py +9 -3
  5. siliconcompiler/tools/__init__.py +1 -1
  6. siliconcompiler/tools/_common/asic.py +3 -0
  7. siliconcompiler/tools/_common/asic_clock.py +101 -0
  8. siliconcompiler/tools/bambu/__init__.py +32 -0
  9. siliconcompiler/tools/bambu/convert.py +93 -12
  10. siliconcompiler/tools/openroad/_apr.py +11 -0
  11. siliconcompiler/tools/openroad/fillmetal_insertion.py +0 -1
  12. siliconcompiler/tools/openroad/init_floorplan.py +7 -1
  13. siliconcompiler/tools/openroad/macro_placement.py +1 -2
  14. siliconcompiler/tools/openroad/pin_placement.py +0 -1
  15. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -2
  16. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +1 -0
  17. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +1 -0
  18. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +24 -0
  19. siliconcompiler/tools/openroad/scripts/common/procs.tcl +2 -1
  20. siliconcompiler/tools/openroad/scripts/common/read_input_files.tcl +1 -0
  21. siliconcompiler/tools/openroad/scripts/common/reports.tcl +0 -13
  22. siliconcompiler/tools/slang/__init__.py +1 -0
  23. siliconcompiler/tools/verilator/verilator.py +1 -0
  24. siliconcompiler/tools/yosys/__init__.py +26 -23
  25. siliconcompiler/tools/yosys/procs.tcl +17 -0
  26. siliconcompiler/tools/yosys/syn_asic.py +12 -65
  27. siliconcompiler/tools/yosys/syn_asic.tcl +6 -51
  28. siliconcompiler/toolscripts/_tools.json +2 -2
  29. siliconcompiler/toolscripts/rhel8/install-yosys.sh +1 -1
  30. siliconcompiler/toolscripts/rhel9/install-openroad.sh +34 -0
  31. siliconcompiler/toolscripts/rhel9/install-yosys.sh +1 -1
  32. siliconcompiler/toolscripts/ubuntu20/install-yosys.sh +1 -1
  33. siliconcompiler/toolscripts/ubuntu22/install-yosys.sh +1 -1
  34. siliconcompiler/toolscripts/ubuntu24/install-yosys.sh +1 -1
  35. siliconcompiler/utils/__init__.py +2 -0
  36. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/METADATA +5 -5
  37. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/RECORD +41 -40
  38. siliconcompiler/tools/bambu/bambu.py +0 -32
  39. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/LICENSE +0 -0
  40. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/WHEEL +0 -0
  41. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/entry_points.txt +0 -0
  42. {siliconcompiler-0.29.3.dist-info → siliconcompiler-0.29.4.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.29.3'
2
+ version = '0.29.4'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -73,16 +73,18 @@ def show_tool(tool, script):
73
73
  def _get_os_name():
74
74
  machine_info = _get_machine_info()
75
75
  system = machine_info.get('system', "").lower()
76
- distro = machine_info.get('distro', "").lower()
77
- osversion = machine_info.get('osversion', "").lower()
78
76
  if system == 'linux':
77
+ distro = machine_info.get('distro', "").lower()
79
78
  if distro == 'ubuntu':
79
+ osversion = machine_info.get('osversion', "").lower()
80
80
  version, _ = osversion.split('.')
81
81
  return f"{distro}{version}"
82
82
  elif distro == 'rocky':
83
+ osversion = machine_info.get('osversion', "").lower()
83
84
  version, _ = osversion.split('.')
84
85
  return f"rhel{version}"
85
86
  elif distro == 'rhel':
87
+ osversion = machine_info.get('osversion', "").lower()
86
88
  version, _ = osversion.split('.')
87
89
  return f"rhel{version}"
88
90
  return None
@@ -134,6 +136,10 @@ def _recommended_tool_groups(tools):
134
136
  for group, group_tools in groups.items():
135
137
  if all([tool in tools for tool in group_tools]):
136
138
  filter_groups[group] = group_tools
139
+ else:
140
+ missing = sorted([tool for tool in group_tools if tool not in tools])
141
+ filter_groups[group] = f"{group} group is not available for {_get_os_name()} " \
142
+ f"due to lack of support for the following tools: {', '.join(missing)}"
137
143
  return filter_groups
138
144
 
139
145
 
@@ -172,6 +178,11 @@ To system debugging information (this should only be used to debug):
172
178
 
173
179
  tools = _get_tools_list()
174
180
 
181
+ if _get_os_name() is None:
182
+ print("Unsupported operating system", file=sys.stderr)
183
+ print_machine_info()
184
+ return 1
185
+
175
186
  tool_choices = ChoiceOptional(tools.keys())
176
187
  parser.add_argument(
177
188
  "tool",
@@ -220,7 +231,11 @@ To system debugging information (this should only be used to debug):
220
231
  args.tool = list(args.tool)
221
232
  if args.group:
222
233
  for group in args.group:
223
- args.tool.extend(tool_groups[group])
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:
@@ -477,6 +477,9 @@ service, provided by SiliconCompiler, is not intended to process proprietary IP.
477
477
  # Flush file to ensure everything is written
478
478
  upload_file.flush()
479
479
 
480
+ # We no longer need the collected files
481
+ shutil.rmtree(self.__chip._getcollectdir(jobname=self.__chip.get('option', 'jobname')))
482
+
480
483
  if 'pre_upload' in remote_status:
481
484
  self.__logger.info(remote_status['pre_upload']['message'])
482
485
  time.sleep(remote_status['pre_upload']['delay'])
@@ -1628,8 +1628,14 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
1628
1628
  # Update dashboard if the manifest changed
1629
1629
  chip._dash.update_manifest()
1630
1630
 
1631
- # TODO: exponential back-off with max?
1632
- time.sleep(0.1)
1631
+ if len(running_nodes) == 1:
1632
+ # if there is only one node running, just join the thread
1633
+ running_node = list(running_nodes.keys())[0]
1634
+ processes[running_node]["proc"].join()
1635
+ elif len(running_nodes) > 1:
1636
+ # if there are more than 1, join the first with a timeout
1637
+ running_node = list(running_nodes.keys())[0]
1638
+ processes[running_node]["proc"].join(timeout=0.1)
1633
1639
 
1634
1640
 
1635
1641
  def _process_completed_nodes(chip, processes, running_nodes):
@@ -1949,7 +1955,7 @@ def check_node_inputs(chip, step, index):
1949
1955
  step=check_step, index=check_index)
1950
1956
 
1951
1957
  if check_hash != prev_hash:
1952
- print_warning(key)
1958
+ print_warning(key, "file hash")
1953
1959
  return False
1954
1960
  else:
1955
1961
  # check timestamps on current files
@@ -1,4 +1,4 @@
1
- from siliconcompiler.tools.bambu import bambu
1
+ from siliconcompiler.tools import bambu
2
2
  from siliconcompiler.tools.bluespec import bluespec
3
3
  from siliconcompiler.tools.builtin import builtin
4
4
  from siliconcompiler.tools.chisel import chisel
@@ -194,6 +194,9 @@ def set_tool_task_lib_var(chip,
194
194
 
195
195
  values.update(chip.get(*lib_key, step=get_step, index=get_index))
196
196
 
197
+ if default_value and not check_value(values):
198
+ values = default_value
199
+
197
200
  if check_value(values):
198
201
  chip.set('tool', tool, 'task', task, 'var', param_key, values,
199
202
  step=step, index=index, clobber=False)
@@ -0,0 +1,101 @@
1
+ import re
2
+ from siliconcompiler.utils import sc_open
3
+ from siliconcompiler.tools._common.asic import get_tool_task
4
+
5
+
6
+ def __get_clock_data(chip, clock_units_multiplier=1):
7
+ step = chip.get('arg', 'step')
8
+ index = chip.get('arg', 'index')
9
+
10
+ period = None
11
+ # get clock information from sdc files
12
+ if chip.valid('input', 'constraint', 'sdc'):
13
+ for sdc in chip.find_files('input', 'constraint', 'sdc', step=step, index=index):
14
+ lines = []
15
+ with sc_open(sdc) as f:
16
+ lines = f.read().splitlines()
17
+
18
+ # collect simple variables in case clock is specified with a variable
19
+ re_var = r"[A-Za-z0-9_]+"
20
+ re_num = r"[0-9\.]+"
21
+ sdc_vars = {}
22
+ for line in lines:
23
+ tcl_variable = re.findall(fr"^\s*set\s+({re_var})\s+({re_num}|\${re_var})", line)
24
+ if tcl_variable:
25
+ var_name, var_value = tcl_variable[0]
26
+ sdc_vars[f'${var_name}'] = var_value
27
+
28
+ # TODO: handle line continuations
29
+ for line in lines:
30
+ clock_period = re.findall(fr"create_clock\s.*-period\s+({re_num}|\${re_var})",
31
+ line)
32
+ if clock_period:
33
+ convert_period = clock_period[0]
34
+ while isinstance(convert_period, str) and convert_period[0] == "$":
35
+ if convert_period in sdc_vars:
36
+ convert_period = sdc_vars[convert_period]
37
+ else:
38
+ break
39
+ if isinstance(convert_period, str) and convert_period[0] == "$":
40
+ chip.logger.warning('Unable to identify clock period from '
41
+ f'{clock_period[0]}.')
42
+ continue
43
+ else:
44
+ try:
45
+ clock_period = float(convert_period)
46
+ except TypeError:
47
+ continue
48
+
49
+ clock_period = clock_period * clock_units_multiplier
50
+
51
+ if period is None:
52
+ period = clock_period
53
+ else:
54
+ period = min(period, clock_period)
55
+
56
+ if period is not None:
57
+ return period, None, [('input', 'constraint', 'sdc')]
58
+
59
+ if period is None:
60
+ keys = []
61
+ key_pin = None
62
+ # get clock information from defined clocks
63
+ for pin in chip.getkeys('datasheet', 'pin'):
64
+ for mode in chip.getkeys('datasheet', 'pin', pin, 'type'):
65
+ if chip.get('datasheet', 'pin', pin, 'type', mode) == 'clock':
66
+ clock_period = min(chip.get('datasheet', 'pin', pin, 'tperiod', mode)) * 1e9
67
+
68
+ if period is None:
69
+ period = clock_period
70
+ keys = [
71
+ ('datasheet', 'pin', pin, 'type', mode),
72
+ ('datasheet', 'pin', pin, 'tperiod', mode)
73
+ ]
74
+ key_pin = pin
75
+ else:
76
+ if clock_period < period:
77
+ period = clock_period
78
+ keys = [
79
+ ('datasheet', 'pin', pin, 'type', mode),
80
+ ('datasheet', 'pin', pin, 'tperiod', mode)
81
+ ]
82
+ key_pin = pin
83
+ return period, key_pin, keys
84
+
85
+ return None, None, []
86
+
87
+
88
+ def add_clock_requirements(chip):
89
+ _, _, keys = __get_clock_data(chip)
90
+
91
+ step = chip.get('arg', 'step')
92
+ index = chip.get('arg', 'index')
93
+ tool, task = get_tool_task(chip, step, index)
94
+ for key in keys:
95
+ chip.add('tool', tool, 'task', task, 'require', ','.join(key),
96
+ step=step, index=index)
97
+
98
+
99
+ def get_clock_period(chip, clock_units_multiplier=1):
100
+ period, name, _ = __get_clock_data(chip, clock_units_multiplier=clock_units_multiplier)
101
+ return name, period
@@ -0,0 +1,32 @@
1
+ '''
2
+ The primary objective of the PandA project is to develop a usable framework that will
3
+ enable the research of new ideas in the HW-SW Co-Design field.
4
+
5
+ The PandA framework includes methodologies supporting the research on high-level synthesis
6
+ of hardware accelerators, on parallelism extraction for embedded systems, on hardware/software
7
+ partitioning and mapping, on metrics for performance estimation of embedded software
8
+ applications and on dynamic reconfigurable devices.
9
+
10
+ Documentation: https://github.com/ferrandi/PandA-bambu
11
+
12
+ Sources: https://github.com/ferrandi/PandA-bambu
13
+
14
+ Installation: https://panda.dei.polimi.it/?page_id=88
15
+ '''
16
+
17
+ from siliconcompiler.tools.bambu import convert
18
+
19
+
20
+ ####################################################################
21
+ # Make Docs
22
+ ####################################################################
23
+ def make_docs(chip):
24
+ convert.setup(chip)
25
+ return chip
26
+
27
+
28
+ def parse_version(stdout):
29
+ # Long multiline output, but second-to-last line looks like:
30
+ # Version: PandA 0.9.6 - Revision 5e5e306b86383a7d85274d64977a3d71fdcff4fe-main
31
+ version_line = stdout.split('\n')[-3]
32
+ return version_line.split()[2]
@@ -1,9 +1,19 @@
1
1
  import os
2
+ import re
2
3
  import shutil
3
- from siliconcompiler import utils
4
+ from siliconcompiler.utils import sc_open
5
+ from siliconcompiler.tools._common.asic import set_tool_task_var, set_tool_task_lib_var, get_mainlib
6
+ from siliconcompiler.tools._common.asic_clock import get_clock_period, add_clock_requirements
4
7
  from siliconcompiler.tools._common import \
5
8
  add_frontend_requires, add_require_input, get_frontend_options, get_input_files, \
6
- get_tool_task, has_input_files
9
+ get_tool_task, has_input_files, record_metric
10
+
11
+
12
+ def make_docs(chip):
13
+ from siliconcompiler.targets import freepdk45_demo
14
+ chip.use(freepdk45_demo)
15
+ chip.input('<design>.c')
16
+ return setup(chip)
7
17
 
8
18
 
9
19
  def setup(chip):
@@ -11,13 +21,13 @@ def setup(chip):
11
21
  Performs high level synthesis to generate a verilog output
12
22
  '''
13
23
 
14
- if not has_input_files(chip, 'input', 'hll', 'c'):
15
- return "no files in [input,hll,c]"
24
+ if not has_input_files(chip, 'input', 'hll', 'c') and \
25
+ not has_input_files(chip, 'input', 'hll', 'llvm'):
26
+ return "no files in [input,hll,c] or [input,hll,llvm]"
16
27
 
17
- tool = 'bambu'
18
28
  step = chip.get('arg', 'step')
19
29
  index = chip.get('arg', 'index')
20
- _, task = get_tool_task(chip, step, index)
30
+ tool, task = get_tool_task(chip, step, index)
21
31
 
22
32
  # Standard Setup
23
33
  refdir = 'tools/' + tool
@@ -28,24 +38,41 @@ def setup(chip):
28
38
  chip.set('tool', tool, 'task', task, 'refdir', refdir,
29
39
  step=step, index=index,
30
40
  package='siliconcompiler', clobber=False)
31
- chip.set('tool', tool, 'task', task, 'threads', utils.get_cores(chip),
32
- step=step, index=index, clobber=False)
33
41
 
34
42
  # Input/Output requirements
35
43
  chip.add('tool', tool, 'task', task, 'output', chip.top() + '.v', step=step, index=index)
36
44
 
45
+ add_clock_requirements(chip)
46
+
37
47
  # Schema requirements
38
48
  add_require_input(chip, 'input', 'hll', 'c')
49
+ add_require_input(chip, 'input', 'hll', 'llvm')
39
50
  add_frontend_requires(chip, ['idir', 'define'])
40
51
 
52
+ set_tool_task_var(chip, 'device',
53
+ schelp="Device to use during bambu synthesis")
54
+ set_tool_task_lib_var(chip, 'memorychannels', default_value=1,
55
+ schelp="Number of memory channels available")
56
+
57
+ # Require clock conversion factor, from library units to ns
58
+ mainlib = get_mainlib(chip)
59
+ chip.add('tool', tool, 'task', task, 'require',
60
+ ','.join(['library', mainlib, 'option', 'var', 'bambu_clock_multiplier']),
61
+ step=step, index=index)
62
+
63
+ set_tool_task_var(chip, 'clock_multiplier',
64
+ schelp="Clock multiplier used to convert library units to ns")
65
+
41
66
 
42
67
  ################################
43
68
  # Custom runtime options
44
69
  ################################
45
70
  def runtime_options(chip):
46
- cmdlist = []
71
+ step = chip.get('arg', 'step')
72
+ index = chip.get('arg', 'index')
73
+ tool, task = get_tool_task(chip, step, index)
47
74
 
48
- cmdlist.append('--memory-allocation-policy=NO_BRAM')
75
+ cmdlist = []
49
76
 
50
77
  opts = get_frontend_options(chip, ['idir', 'define'])
51
78
 
@@ -55,11 +82,34 @@ def runtime_options(chip):
55
82
  cmdlist.append('-D' + value)
56
83
  for value in get_input_files(chip, 'input', 'hll', 'c'):
57
84
  cmdlist.append(value)
85
+ if not has_input_files(chip, 'input', 'hll', 'c'):
86
+ # Only use llvm if C is empty
87
+ for value in get_input_files(chip, 'input', 'hll', 'llvm'):
88
+ cmdlist.append(value)
58
89
 
90
+ cmdlist.append('--soft-float')
59
91
  cmdlist.append('--memory-allocation-policy=NO_BRAM')
60
92
 
61
- step = chip.get('arg', 'step')
62
- index = chip.get('arg', 'index')
93
+ mem_channels = int(chip.get('tool', tool, 'task', task, 'var', 'memorychannels',
94
+ step=step, index=index)[0])
95
+ if mem_channels > 0:
96
+ cmdlist.append(f'--channels-number={mem_channels}')
97
+
98
+ mainlib = get_mainlib(chip)
99
+ clock_multiplier = float(chip.get('library', mainlib, 'option', 'var',
100
+ 'bambu_clock_multiplier')[0])
101
+ clock_name, period = get_clock_period(chip, clock_units_multiplier=clock_multiplier)
102
+ if clock_name:
103
+ cmdlist.append(f'--clock-name={clock_name}')
104
+ if period:
105
+ cmdlist.append(f'--clock-period={period}')
106
+
107
+ cmdlist.append('--disable-function-proxy')
108
+
109
+ device = chip.get('tool', tool, 'task', task, 'var', 'device',
110
+ step=step, index=index)
111
+ if device:
112
+ cmdlist.append(f'--device={device[0]}')
63
113
 
64
114
  cmdlist.append(f'--top-fname={chip.top(step, index)}')
65
115
 
@@ -76,3 +126,34 @@ def post_process(chip):
76
126
  index = chip.get('arg', 'index')
77
127
 
78
128
  shutil.copy2(f'{chip.top(step, index)}.v', os.path.join('outputs', f'{chip.top()}.v'))
129
+
130
+ ff = re.compile(fr"Total number of flip-flops in function {chip.top(step, index)}: (\d+)")
131
+ area = re.compile(r"Total estimated area: (\d+)")
132
+ fmax = re.compile(r"Estimated max frequency \(MHz\): (\d+\.?\d*)")
133
+ slack = re.compile(r"Minimum slack: (\d+\.?\d*)")
134
+
135
+ log_file = f"{step}.log"
136
+ with sc_open(log_file) as log:
137
+ for line in log:
138
+ ff_match = ff.findall(line)
139
+ area_match = area.findall(line)
140
+ fmax_match = fmax.findall(line)
141
+ slack_match = slack.findall(line)
142
+ if ff_match:
143
+ record_metric(chip, step, index, "registers", int(ff_match[0]), log_file)
144
+ if area_match:
145
+ record_metric(chip, step, index, "cellarea", float(area_match[0]), log_file,
146
+ source_unit='um^2')
147
+ if fmax_match:
148
+ record_metric(chip, step, index, "fmax", float(fmax_match[0]), log_file,
149
+ source_unit='MHz')
150
+ if slack_match:
151
+ slack_ns = float(slack_match[0])
152
+ if slack_ns >= 0:
153
+ record_metric(chip, step, index, "setupwns", 0, log_file,
154
+ source_unit='ns')
155
+ else:
156
+ record_metric(chip, step, index, "setupwns", slack_ns, log_file,
157
+ source_unit='ns')
158
+ record_metric(chip, step, index, "setupslack", slack_ns, log_file,
159
+ source_unit='ns')
@@ -148,6 +148,10 @@ def extract_metrics(chip):
148
148
 
149
149
  metrics_file = "reports/metrics.json"
150
150
 
151
+ if not os.path.exists(metrics_file):
152
+ chip.logger.warning("OpenROAD metrics file is missing")
153
+ return
154
+
151
155
  def get_metric_sources(metric):
152
156
  metric_sources = [metrics_file]
153
157
  if metric in metric_reports:
@@ -572,6 +576,13 @@ def define_rsz_params(chip):
572
576
  default_value='100',
573
577
  schelp='percentage of violating nets to attempt to repair (0 - 100)')
574
578
 
579
+ set_tool_task_var(chip, param_key='rsz_skip_recover_power',
580
+ default_value=False,
581
+ schelp='skip power recovery')
582
+ set_tool_task_var(chip, param_key='rsz_recover_power',
583
+ default_value=100,
584
+ schelp='percentage of paths to attempt to recover power (0 - 100)')
585
+
575
586
  step = chip.get('arg', 'step')
576
587
  index = chip.get('arg', 'index')
577
588
  tool, task = get_tool_task(chip, step, index)
@@ -43,7 +43,6 @@ def setup(chip):
43
43
  'hold',
44
44
  'unconstrained',
45
45
  'clock_skew',
46
- 'power',
47
46
  'drv_violations',
48
47
  'fmax',
49
48
 
@@ -1,5 +1,5 @@
1
1
  from siliconcompiler.tools._common import input_provides, add_common_file, get_tool_task
2
- from siliconcompiler.tools._common.asic import set_tool_task_var
2
+ from siliconcompiler.tools._common.asic import set_tool_task_var, get_mainlib
3
3
 
4
4
  from siliconcompiler.tools.openroad._apr import setup as apr_setup
5
5
  from siliconcompiler.tools.openroad._apr import set_reports, set_pnr_inputs, set_pnr_outputs
@@ -74,6 +74,8 @@ def setup(chip):
74
74
  'power'
75
75
  ])
76
76
 
77
+ mainlib = get_mainlib(chip)
78
+
77
79
  # Setup required
78
80
  for component in chip.getkeys('constraint', 'component'):
79
81
  for key in chip.getkeys('constraint', 'component', component):
@@ -92,6 +94,10 @@ def setup(chip):
92
94
  chip.add('tool', tool, 'task', task, 'require',
93
95
  ','.join(['constraint', ifp]),
94
96
  step=step, index=index)
97
+ if chip.valid('library', mainlib, 'option', 'file', 'openroad_tracks'):
98
+ chip.add('tool', tool, 'task', task, 'require',
99
+ ','.join(['library', mainlib, 'option', 'file', 'openroad_tracks']),
100
+ step=step, index=index)
95
101
 
96
102
 
97
103
  def pre_process(chip):
@@ -40,8 +40,7 @@ def setup(chip):
40
40
 
41
41
  set_reports(chip, [
42
42
  'setup',
43
- 'unconstrained',
44
- 'power'
43
+ 'unconstrained'
45
44
  ])
46
45
 
47
46
 
@@ -38,7 +38,6 @@ def setup(chip):
38
38
  set_reports(chip, [
39
39
  'setup',
40
40
  'unconstrained',
41
- 'power',
42
41
 
43
42
  # Images
44
43
  'placement_density',
@@ -91,5 +91,6 @@ if { [llength $openroad_dont_touch] > 0 } {
91
91
  # set don't touch list
92
92
  set_dont_touch $openroad_dont_touch
93
93
  }
94
- tee -file reports/dont_touch.start.rpt {report_dont_touch}
95
- tee -file reports/dont_use.start.rpt {report_dont_use}
94
+ tee -quiet -file reports/dont_touch.start.rpt {report_dont_touch}
95
+ tee -quiet -file reports/dont_use.start.rpt {report_dont_use}
96
+ tee -file reports/global_connections.start.rpt {report_global_connect}
@@ -25,6 +25,7 @@ if { [sc_cfg_tool_task_exists {file} global_connect] } {
25
25
  source $global_connect
26
26
  }
27
27
  }
28
+ tee -file reports/global_connections.rpt {report_global_connect}
28
29
 
29
30
  ###############################
30
31
  # Initialize floorplan
@@ -33,6 +33,7 @@ foreach pdnconfig [sc_cfg_tool_task_get {file} pdn_config] {
33
33
 
34
34
  lappend pdn_files $pdnconfig
35
35
  }
36
+ tee -quiet -file reports/power_grid_configuration.rpt {pdngen -report_only}
36
37
  pdngen -failed_via_report "reports/${sc_design}_pdngen_failed_vias.rpt"
37
38
 
38
39
  ###############################
@@ -20,6 +20,7 @@ set rsz_hold_slack_margin [lindex [sc_cfg_tool_task_get {var} rsz_hold_slack_mar
20
20
  set rsz_slew_margin [lindex [sc_cfg_tool_task_get {var} rsz_slew_margin] 0]
21
21
  set rsz_cap_margin [lindex [sc_cfg_tool_task_get {var} rsz_cap_margin] 0]
22
22
  set rsz_repair_tns [lindex [sc_cfg_tool_task_get {var} rsz_repair_tns] 0]
23
+ set rsz_recover_power [lindex [sc_cfg_tool_task_get {var} rsz_recover_power] 0]
23
24
 
24
25
  set repair_timing_args []
25
26
  if { [lindex [sc_cfg_tool_task_get {var} rsz_skip_pin_swap] 0] == "true" } {
@@ -77,6 +78,29 @@ if { [lindex [sc_cfg_tool_task_get var rsz_skip_hold_repair] 0] != "true" } {
77
78
  sc_set_dont_use
78
79
  }
79
80
 
81
+ if { [lindex [sc_cfg_tool_task_get var rsz_skip_recover_power] 0] != "true" } {
82
+ ###############################
83
+ # Recover power
84
+ ###############################
85
+
86
+ estimate_parasitics -placement
87
+
88
+ # Enable cells
89
+ sc_set_dont_use -hold -scanchain -multibit -report dont_use.repair_timing.power
90
+
91
+ repair_timing \
92
+ -recover_power $rsz_recover_power \
93
+ -verbose \
94
+ -setup_margin $rsz_setup_slack_margin \
95
+ -hold_margin $rsz_hold_slack_margin \
96
+ {*}$repair_timing_args
97
+
98
+ sc_detailed_placement
99
+
100
+ # Restore dont use
101
+ sc_set_dont_use
102
+ }
103
+
80
104
  global_connect
81
105
 
82
106
  # estimate for metrics
@@ -758,6 +758,7 @@ proc sc_set_dont_use { args } {
758
758
  }
759
759
 
760
760
  if { [info exists keys(-report)] } {
761
- tee -file reports/$keys(-report).rpt {report_dont_use}
761
+ puts "Dont use report: reports/$keys(-report).rpt"
762
+ tee -quiet -file reports/$keys(-report).rpt {report_dont_use}
762
763
  }
763
764
  }
@@ -56,4 +56,5 @@ if { [sc_has_input_files odb "input layout odb"] } {
56
56
  source $global_connect
57
57
  }
58
58
  }
59
+ tee -file reports/global_connections.rpt {report_global_connect}
59
60
  }
@@ -168,17 +168,4 @@ foreach markerdb [[ord::get_db_block] getMarkerCategories] {
168
168
 
169
169
  utl::push_metrics_stage "sc__cellarea__{}"
170
170
  tee -file reports/cell_usage.rpt {report_cell_usage -verbose}
171
-
172
- foreach modinst [[ord::get_db_block] getModInsts] {
173
- tee -quiet -append -file reports/cell_usage.rpt { puts "" }
174
- tee -quiet -append -file reports/cell_usage.rpt {
175
- puts "########################################################"
176
- }
177
- tee -quiet -append -file reports/cell_usage.rpt { puts "" }
178
-
179
- utl::metric "design__instance__name__in_module:[[$modinst getMaster] getName]" \
180
- [$modinst getHierarchicalName]
181
- tee -quiet -append -file reports/cell_usage.rpt \
182
- "report_cell_usage -verbose [$modinst getHierarchicalName]"
183
- }
184
171
  utl::pop_metrics_stage
@@ -120,6 +120,7 @@ def common_runtime_options(chip):
120
120
  ###############################
121
121
  # Set up user-provided parameters to ensure we elaborate the correct modules
122
122
  for param, value in opts['param']:
123
+ value = value.replace('"', '\\"')
123
124
  options.append(f'-G {param}={value}')
124
125
 
125
126
  return options
@@ -137,6 +137,7 @@ def runtime_options(chip):
137
137
  cmdlist.append(value)
138
138
 
139
139
  for param, value in frontend_opts['param']:
140
+ value = value.replace('"', '\\"')
140
141
  cmdlist.append(f'-G{param}={value}')
141
142
 
142
143
  if os.path.isfile(f'inputs/{design}.v'):