siliconcompiler 0.33.2__py3-none-any.whl → 0.34.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.
Files changed (104) hide show
  1. siliconcompiler/__init__.py +2 -0
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/_common.py +1 -1
  4. siliconcompiler/apps/sc.py +1 -1
  5. siliconcompiler/apps/sc_issue.py +6 -4
  6. siliconcompiler/apps/sc_remote.py +3 -20
  7. siliconcompiler/apps/sc_show.py +2 -2
  8. siliconcompiler/apps/utils/replay.py +4 -4
  9. siliconcompiler/checklist.py +202 -1
  10. siliconcompiler/core.py +62 -293
  11. siliconcompiler/data/templates/email/general.j2 +3 -3
  12. siliconcompiler/data/templates/email/summary.j2 +1 -1
  13. siliconcompiler/data/templates/issue/README.txt +1 -1
  14. siliconcompiler/data/templates/report/sc_report.j2 +7 -7
  15. siliconcompiler/dependencyschema.py +392 -0
  16. siliconcompiler/design.py +758 -0
  17. siliconcompiler/flowgraph.py +79 -13
  18. siliconcompiler/optimizer/vizier.py +2 -2
  19. siliconcompiler/package/__init__.py +383 -223
  20. siliconcompiler/package/git.py +75 -77
  21. siliconcompiler/package/github.py +70 -97
  22. siliconcompiler/package/https.py +77 -93
  23. siliconcompiler/packageschema.py +260 -0
  24. siliconcompiler/pdk.py +5 -5
  25. siliconcompiler/remote/client.py +33 -15
  26. siliconcompiler/remote/server.py +2 -2
  27. siliconcompiler/report/dashboard/cli/__init__.py +6 -6
  28. siliconcompiler/report/dashboard/cli/board.py +4 -4
  29. siliconcompiler/report/dashboard/web/components/__init__.py +5 -5
  30. siliconcompiler/report/dashboard/web/components/flowgraph.py +4 -4
  31. siliconcompiler/report/dashboard/web/components/graph.py +2 -2
  32. siliconcompiler/report/dashboard/web/state.py +1 -1
  33. siliconcompiler/report/dashboard/web/utils/__init__.py +5 -5
  34. siliconcompiler/report/html_report.py +1 -1
  35. siliconcompiler/report/report.py +4 -4
  36. siliconcompiler/report/summary_table.py +2 -2
  37. siliconcompiler/report/utils.py +5 -5
  38. siliconcompiler/scheduler/__init__.py +3 -1382
  39. siliconcompiler/scheduler/docker.py +263 -0
  40. siliconcompiler/scheduler/run_node.py +10 -21
  41. siliconcompiler/scheduler/scheduler.py +311 -0
  42. siliconcompiler/scheduler/schedulernode.py +944 -0
  43. siliconcompiler/scheduler/send_messages.py +3 -3
  44. siliconcompiler/scheduler/slurm.py +149 -163
  45. siliconcompiler/scheduler/taskscheduler.py +45 -57
  46. siliconcompiler/schema/__init__.py +3 -3
  47. siliconcompiler/schema/baseschema.py +234 -11
  48. siliconcompiler/schema/editableschema.py +4 -0
  49. siliconcompiler/schema/journal.py +210 -0
  50. siliconcompiler/schema/namedschema.py +55 -2
  51. siliconcompiler/schema/parameter.py +14 -1
  52. siliconcompiler/schema/parametervalue.py +1 -34
  53. siliconcompiler/schema/schema_cfg.py +210 -349
  54. siliconcompiler/tool.py +412 -148
  55. siliconcompiler/tools/__init__.py +2 -0
  56. siliconcompiler/tools/builtin/_common.py +5 -5
  57. siliconcompiler/tools/builtin/concatenate.py +7 -7
  58. siliconcompiler/tools/builtin/minimum.py +4 -4
  59. siliconcompiler/tools/builtin/mux.py +4 -4
  60. siliconcompiler/tools/builtin/nop.py +4 -4
  61. siliconcompiler/tools/builtin/verify.py +8 -9
  62. siliconcompiler/tools/execute/exec_input.py +1 -1
  63. siliconcompiler/tools/genfasm/genfasm.py +1 -6
  64. siliconcompiler/tools/openroad/_apr.py +5 -1
  65. siliconcompiler/tools/openroad/antenna_repair.py +1 -1
  66. siliconcompiler/tools/openroad/macro_placement.py +1 -1
  67. siliconcompiler/tools/openroad/power_grid.py +1 -1
  68. siliconcompiler/tools/openroad/scripts/common/procs.tcl +32 -25
  69. siliconcompiler/tools/opensta/timing.py +26 -3
  70. siliconcompiler/tools/slang/__init__.py +2 -2
  71. siliconcompiler/tools/surfer/__init__.py +0 -0
  72. siliconcompiler/tools/surfer/show.py +53 -0
  73. siliconcompiler/tools/surfer/surfer.py +30 -0
  74. siliconcompiler/tools/vpr/route.py +82 -0
  75. siliconcompiler/tools/vpr/vpr.py +23 -6
  76. siliconcompiler/tools/yosys/__init__.py +1 -1
  77. siliconcompiler/tools/yosys/scripts/procs.tcl +143 -0
  78. siliconcompiler/tools/yosys/{sc_synth_asic.tcl → scripts/sc_synth_asic.tcl} +4 -0
  79. siliconcompiler/tools/yosys/{sc_synth_fpga.tcl → scripts/sc_synth_fpga.tcl} +24 -77
  80. siliconcompiler/tools/yosys/syn_fpga.py +14 -0
  81. siliconcompiler/toolscripts/_tools.json +9 -13
  82. siliconcompiler/toolscripts/rhel9/install-vpr.sh +0 -2
  83. siliconcompiler/toolscripts/ubuntu22/install-surfer.sh +33 -0
  84. siliconcompiler/toolscripts/ubuntu24/install-surfer.sh +33 -0
  85. siliconcompiler/utils/__init__.py +4 -24
  86. siliconcompiler/utils/flowgraph.py +29 -28
  87. siliconcompiler/utils/issue.py +23 -29
  88. siliconcompiler/utils/logging.py +37 -7
  89. siliconcompiler/utils/showtools.py +6 -1
  90. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/METADATA +16 -25
  91. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/RECORD +98 -91
  92. siliconcompiler/scheduler/docker_runner.py +0 -254
  93. siliconcompiler/schema/journalingschema.py +0 -242
  94. siliconcompiler/tools/yosys/procs.tcl +0 -71
  95. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +0 -68
  96. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +0 -68
  97. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +0 -68
  98. /siliconcompiler/tools/yosys/{sc_lec.tcl → scripts/sc_lec.tcl} +0 -0
  99. /siliconcompiler/tools/yosys/{sc_screenshot.tcl → scripts/sc_screenshot.tcl} +0 -0
  100. /siliconcompiler/tools/yosys/{syn_strategies.tcl → scripts/syn_strategies.tcl} +0 -0
  101. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/WHEEL +0 -0
  102. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/entry_points.txt +0 -0
  103. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/licenses/LICENSE +0 -0
  104. {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.1.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,7 @@ from siliconcompiler.tools import openroad
18
18
  from siliconcompiler.tools import opensta
19
19
  from siliconcompiler.tools import slang
20
20
  from siliconcompiler.tools import surelog
21
+ from siliconcompiler.tools import surfer
21
22
  from siliconcompiler.tools.sv2v import sv2v
22
23
  from siliconcompiler.tools.verilator import verilator
23
24
  from siliconcompiler.tools.vivado import vivado
@@ -53,6 +54,7 @@ def get_tools():
53
54
  opensta,
54
55
  slang,
55
56
  surelog,
57
+ surfer,
56
58
  sv2v,
57
59
  verilator,
58
60
  vivado,
@@ -83,10 +83,10 @@ def _minmax(chip, *nodes, op=None):
83
83
  real = chip.get('metric', metric, step=step, index=index)
84
84
  if real is None:
85
85
  raise SiliconCompilerError(
86
- f'Metric {metric} has goal for {step}{index} '
86
+ f'Metric {metric} has goal for {step}/{index} '
87
87
  'but it has not been set.', chip=chip)
88
88
  if abs(real) > goal:
89
- chip.logger.warning(f"Step {step}{index} failed "
89
+ chip.logger.warning(f"Step {step}/{index} failed "
90
90
  f"because it didn't meet goals for '{metric}' "
91
91
  "metric.")
92
92
  failed[step][index] = True
@@ -122,7 +122,7 @@ def _minmax(chip, *nodes, op=None):
122
122
  real = chip.get('metric', metric, step=step, index=index)
123
123
  if real is None:
124
124
  raise SiliconCompilerError(
125
- f'Metric {metric} has weight for {step}{index} '
125
+ f'Metric {metric} has weight for {step}/{index} '
126
126
  'but it has not been set.', chip=chip)
127
127
 
128
128
  if not (max_val[metric] - min_val[metric]) == 0:
@@ -153,10 +153,10 @@ def _select_inputs(chip, step, index):
153
153
 
154
154
  flow = chip.get('option', 'flow')
155
155
 
156
- flow_schema = chip.schema.get("flowgraph", flow, field="schema")
156
+ flow_schema = chip.get("flowgraph", flow, field="schema")
157
157
  runtime = RuntimeFlowgraph(
158
158
  flow_schema,
159
159
  from_steps=set([step for step, _ in flow_schema.get_entry_nodes()]),
160
160
  prune_nodes=chip.get('option', 'prune'))
161
161
 
162
- return runtime.get_node_inputs(step, index, record=chip.schema.get("record", field="schema"))
162
+ return runtime.get_node_inputs(step, index, record=chip.get("record", field="schema"))
@@ -3,7 +3,7 @@ import os
3
3
  from siliconcompiler import sc_open, SiliconCompilerError
4
4
  from siliconcompiler import utils
5
5
  from siliconcompiler.tools._common import input_provides, input_file_node_name, get_tool_task
6
- from siliconcompiler import scheduler
6
+ from siliconcompiler.scheduler.schedulernode import SchedulerNode
7
7
 
8
8
 
9
9
  def make_docs(chip):
@@ -11,8 +11,8 @@ def make_docs(chip):
11
11
  _make_docs(chip)
12
12
  chip.set('option', 'flow', 'asicflow')
13
13
 
14
- for step, index in chip.schema.get("flowgraph", "asicflow", field="schema").get_entry_nodes():
15
- scheduler._setup_node(chip, step, index)
14
+ for step, index in chip.get("flowgraph", "asicflow", field="schema").get_entry_nodes():
15
+ SchedulerNode(chip, step, index).setup()
16
16
 
17
17
  chip.set('arg', 'step', 'import.combine')
18
18
  chip.set('arg', 'index', '0')
@@ -64,10 +64,10 @@ def _gather_outputs(chip, step, index):
64
64
  in_nodes = chip.get('flowgraph', flow, step, index, 'input')
65
65
  in_task_outputs = []
66
66
  for in_step, in_index in in_nodes:
67
- in_tool, _ = get_tool_task(chip, in_step, in_index, flow=flow)
68
- task_class = chip.get("tool", in_tool, field="schema")
69
- task_class.set_runtime(chip, step=in_step, index=in_index)
70
- in_task_outputs.append(task_class.get_output_files())
67
+ in_tool, in_task = get_tool_task(chip, in_step, in_index, flow=flow)
68
+ task_class = chip.get("tool", in_tool, "task", in_task, field="schema")
69
+ with task_class.runtime(chip, step=in_step, index=in_index) as task:
70
+ in_task_outputs.append(task.get_output_files())
71
71
 
72
72
  if len(in_task_outputs) > 0:
73
73
  return in_task_outputs[0].union(*in_task_outputs[1:])
@@ -43,10 +43,10 @@ def _gather_outputs(chip, step, index):
43
43
  in_nodes = chip.get('flowgraph', flow, step, index, 'input')
44
44
  in_task_outputs = []
45
45
  for in_step, in_index in in_nodes:
46
- in_tool, _ = get_tool_task(chip, in_step, in_index, flow=flow)
47
- task_class = chip.get("tool", in_tool, field="schema")
48
- task_class.set_runtime(chip, step=in_step, index=in_index)
49
- in_task_outputs.append(task_class.get_output_files())
46
+ in_tool, in_task = get_tool_task(chip, in_step, in_index, flow=flow)
47
+ task_class = chip.get("tool", in_tool, "task", in_task, field="schema")
48
+ with task_class.runtime(chip, step=in_step, index=in_index) as task:
49
+ in_task_outputs.append(task.get_output_files())
50
50
 
51
51
  if len(in_task_outputs) > 0:
52
52
  return in_task_outputs[0].intersection(*in_task_outputs[1:])
@@ -57,10 +57,10 @@ def _gather_outputs(chip, step, index):
57
57
  in_nodes = chip.get('flowgraph', flow, step, index, 'input')
58
58
  in_task_outputs = []
59
59
  for in_step, in_index in in_nodes:
60
- in_tool, _ = get_tool_task(chip, in_step, in_index, flow=flow)
61
- task_class = chip.get("tool", in_tool, field="schema")
62
- task_class.set_runtime(chip, step=in_step, index=in_index)
63
- in_task_outputs.append(task_class.get_output_files())
60
+ in_tool, in_task = get_tool_task(chip, in_step, in_index, flow=flow)
61
+ task_class = chip.get("tool", in_tool, "task", in_task, field="schema")
62
+ with task_class.runtime(chip, step=in_step, index=in_index) as task:
63
+ in_task_outputs.append(task.get_output_files())
64
64
 
65
65
  if len(in_task_outputs) > 0:
66
66
  return in_task_outputs[0].intersection(*in_task_outputs[1:])
@@ -24,10 +24,10 @@ def _gather_outputs(chip, step, index):
24
24
  in_nodes = chip.get('flowgraph', flow, step, index, 'input')
25
25
  in_task_outputs = []
26
26
  for in_step, in_index in in_nodes:
27
- in_tool, _ = get_tool_task(chip, in_step, in_index, flow=flow)
28
- task_class = chip.get("tool", in_tool, field="schema")
29
- task_class.set_runtime(chip, step=in_step, index=in_index)
30
- in_task_outputs.append(task_class.get_output_files())
27
+ in_tool, in_task = get_tool_task(chip, in_step, in_index, flow=flow)
28
+ task_class = chip.get("tool", in_tool, "task", in_task, field="schema")
29
+ with task_class.runtime(chip, step=in_step, index=in_index) as task:
30
+ in_task_outputs.append(task.get_output_files())
31
31
 
32
32
  if len(in_task_outputs) > 0:
33
33
  return in_task_outputs[0].union(*in_task_outputs[1:])
@@ -1,6 +1,5 @@
1
1
  from siliconcompiler.tools.builtin import _common
2
2
  from siliconcompiler.schema.parametertype import NodeType
3
- from siliconcompiler.scheduler import _haltstep
4
3
  from siliconcompiler.tools.builtin.builtin import set_io_files
5
4
  from siliconcompiler import utils, SiliconCompilerError
6
5
  from siliconcompiler.tools._common import get_tool_task
@@ -26,13 +25,13 @@ def _select_inputs(chip, step, index):
26
25
  inputs = _common._select_inputs(chip, step, index)
27
26
  if len(inputs) != 1:
28
27
  raise SiliconCompilerError(
29
- f'{step}{index} receives {len(inputs)} inputs, but only supports one', chip=chip)
28
+ f'{step}/{index} receives {len(inputs)} inputs, but only supports one', chip=chip)
30
29
  inputs = inputs[0]
31
30
  flow = chip.get('option', 'flow')
32
31
  arguments = chip.get('flowgraph', flow, step, index, 'args')
33
32
 
34
33
  if len(arguments) == 0:
35
- raise SiliconCompilerError(f'{step}{index} requires arguments for verify', chip=chip)
34
+ raise SiliconCompilerError(f'{step}/{index} requires arguments for verify', chip=chip)
36
35
 
37
36
  passes = True
38
37
  for criteria in arguments:
@@ -56,10 +55,10 @@ def _select_inputs(chip, step, index):
56
55
  metric_type = chip.get('metric', metric, field=None)
57
56
  goal = NodeType.normalize(goal, metric_type.get(field='type'))
58
57
  if not utils.safecompare(chip, value, op, goal):
59
- chip.error(f"{step}{index} fails '{metric}' metric: {value}{op}{goal}")
58
+ chip.error(f"{step}/{index} fails '{metric}' metric: {value}{op}{goal}")
60
59
 
61
60
  if not passes:
62
- _haltstep(chip, flow, step, index)
61
+ return []
63
62
 
64
63
  return inputs
65
64
 
@@ -70,10 +69,10 @@ def _gather_outputs(chip, step, index):
70
69
  in_nodes = chip.get('flowgraph', flow, step, index, 'input')
71
70
  in_task_outputs = []
72
71
  for in_step, in_index in in_nodes:
73
- in_tool, _ = get_tool_task(chip, in_step, in_index, flow=flow)
74
- task_class = chip.get("tool", in_tool, field="schema")
75
- task_class.set_runtime(chip, step=in_step, index=in_index)
76
- in_task_outputs.append(task_class.get_output_files())
72
+ in_tool, in_task = get_tool_task(chip, in_step, in_index, flow=flow)
73
+ task_class = chip.get("tool", in_tool, "task", in_task, field="schema")
74
+ with task_class.runtime(chip, step=in_step, index=in_index) as task:
75
+ in_task_outputs.append(task.get_output_files())
77
76
 
78
77
  if len(in_task_outputs) > 0:
79
78
  return in_task_outputs[0].intersection(*in_task_outputs[1:])
@@ -34,7 +34,7 @@ def pre_process(chip):
34
34
  break
35
35
 
36
36
  if not exec:
37
- chip.error(f'{step}{index} did not receive an executable file')
37
+ chip.error(f'{step}/{index} did not receive an executable file')
38
38
 
39
39
  chip.set('tool', tool, 'exe', exec)
40
40
 
@@ -1,5 +1,4 @@
1
1
  from siliconcompiler.tools.vpr.vpr import parse_version as vpr_parse_version
2
- from siliconcompiler.tools.vpr.vpr import normalize_version as vpr_normalize_version
3
2
  from siliconcompiler.tools.vpr.vpr import add_tool_requirements as add_vpr_requirements
4
3
 
5
4
  '''
@@ -24,7 +23,7 @@ def make_docs(chip):
24
23
  def setup(chip):
25
24
  chip.set('tool', 'genfasm', 'exe', 'genfasm', clobber=False)
26
25
  chip.set('tool', 'genfasm', 'vswitch', '--version')
27
- chip.set('tool', 'genfasm', 'version', '>=9.0.0', clobber=False)
26
+ chip.set('tool', 'genfasm', 'version', '>=v8.0.0-12677', clobber=False)
28
27
 
29
28
  add_tool_requirements(chip)
30
29
 
@@ -37,10 +36,6 @@ def parse_version(chip):
37
36
  return vpr_parse_version(chip)
38
37
 
39
38
 
40
- def normalize_version(chip):
41
- return vpr_normalize_version(chip)
42
-
43
-
44
39
  ##################################################
45
40
  if __name__ == "__main__":
46
41
  chip = make_docs()
@@ -646,6 +646,10 @@ def define_gpl_params(chip):
646
646
  default_value='true',
647
647
  schelp='true/false, when enabled a global placement is performed without '
648
648
  'considering the impact of the pin placements')
649
+ set_tool_task_var(chip, param_key='gpl_enable_skip_initial_place',
650
+ default_value='false',
651
+ schelp='true/false, when enabled a global placement skips the initial '
652
+ 'placement, before the main global placement pass.')
649
653
 
650
654
 
651
655
  def define_dpo_params(chip):
@@ -654,7 +658,7 @@ def define_dpo_params(chip):
654
658
  schelp='true/false, when true the detailed placement optimization '
655
659
  'will be performed')
656
660
  set_tool_task_var(chip, param_key='dpo_max_displacement',
657
- default_value='0',
661
+ default_value='5',
658
662
  schelp='maximum cell movement in detailed placement optimization in microns, '
659
663
  '0 will result in the tool default maximum displacement')
660
664
 
@@ -68,7 +68,7 @@ def pre_process(chip):
68
68
  chip.get('tool', tool, 'task', task, 'var', 'ant_check',
69
69
  step=step, index=index)[0] == 'false':
70
70
  chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
71
- chip.logger.warning(f'{step}{index} will be skipped since antenna repair is disabled.')
71
+ chip.logger.warning(f'{step}/{index} will be skipped since antenna repair is disabled.')
72
72
  return
73
73
 
74
74
  define_ord_files(chip)
@@ -62,7 +62,7 @@ def pre_process(chip):
62
62
  for in_step, in_index in input_nodes
63
63
  ]):
64
64
  chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
65
- chip.logger.warning(f'{step}{index} will be skipped since are no macros to place.')
65
+ chip.logger.warning(f'{step}/{index} will be skipped since are no macros to place.')
66
66
  return
67
67
 
68
68
  build_pex_corners(chip)
@@ -60,7 +60,7 @@ def pre_process(chip):
60
60
  (chip.get('tool', tool, 'task', task, 'var', 'pdn_enable',
61
61
  step=step, index=index)[0] == 'false' or len(pdncfg) == 0):
62
62
  chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
63
- chip.logger.warning(f'{step}{index} will be skipped since power grid is disabled.')
63
+ chip.logger.warning(f'{step}/{index} will be skipped since power grid is disabled.')
64
64
  return
65
65
 
66
66
  define_ord_files(chip)
@@ -68,6 +68,8 @@ proc sc_global_placement { args } {
68
68
  set gpl_routability_driven [lindex [sc_cfg_tool_task_get var gpl_routability_driven] 0]
69
69
  set gpl_timing_driven [lindex [sc_cfg_tool_task_get var gpl_timing_driven] 0]
70
70
  set gpl_padding [lindex [sc_cfg_tool_task_get var pad_global_place] 0]
71
+ set gpl_enable_skip_initial_place [lindex \
72
+ [sc_cfg_tool_task_get var gpl_enable_skip_initial_place] 0]
71
73
 
72
74
  set gpl_args []
73
75
  if {
@@ -79,6 +81,9 @@ proc sc_global_placement { args } {
79
81
  if { $gpl_timing_driven == "true" } {
80
82
  lappend gpl_args "-timing_driven"
81
83
  }
84
+ if { $gpl_enable_skip_initial_place == "true" } {
85
+ lappend gpl_args "-skip_initial_place"
86
+ }
82
87
 
83
88
  if { [info exists flags(-skip_io)] } {
84
89
  lappend gpl_args "-skip_io"
@@ -634,36 +639,38 @@ proc sc_setup_sta { } {
634
639
  set_timing_derate -late $sta_late_timing_derate
635
640
  }
636
641
 
637
- # Create path groups
638
- if {
639
- [lindex [sc_cfg_tool_task_get var sta_define_path_groups] 0] == "true" &&
640
- [llength [sta::path_group_names]] == 0
641
- } {
642
- sc_path_group -name in2out -from [all_inputs -no_clocks] -to [all_outputs]
643
-
642
+ if { [sc_check_version 19370] } {
643
+ # Create path groups
644
644
  if {
645
- [llength [all_clocks]] == 1 ||
646
- [lindex [sc_cfg_tool_task_get var sta_unique_path_groups_per_clock] 0] == "false"
645
+ [lindex [sc_cfg_tool_task_get var sta_define_path_groups] 0] == "true" &&
646
+ [llength [sta::path_group_names]] == 0
647
647
  } {
648
- sc_path_group -name in2reg -from [all_inputs -no_clocks] -to [all_registers]
649
- sc_path_group -name reg2reg -from [all_registers] -to [all_registers]
650
- sc_path_group -name reg2out -from [all_registers] -to [all_outputs]
651
- } else {
652
- foreach clock [all_clocks] {
653
- set clk_name [get_property $clock name]
654
- sc_path_group -name in2reg.${clk_name} \
655
- -from [all_inputs -no_clocks] \
656
- -to [all_registers -clock $clock]
657
- sc_path_group -name reg2reg.${clk_name} \
658
- -from [all_registers -clock $clock] \
659
- -to [all_registers -clock $clock]
660
- sc_path_group -name reg2out.${clk_name} \
661
- -from [all_registers -clock $clock] \
662
- -to [all_outputs]
648
+ sc_path_group -name in2out -from [all_inputs -no_clocks] -to [all_outputs]
649
+
650
+ if {
651
+ [llength [all_clocks]] == 1 ||
652
+ [lindex [sc_cfg_tool_task_get var sta_unique_path_groups_per_clock] 0] == "false"
653
+ } {
654
+ sc_path_group -name in2reg -from [all_inputs -no_clocks] -to [all_registers]
655
+ sc_path_group -name reg2reg -from [all_registers] -to [all_registers]
656
+ sc_path_group -name reg2out -from [all_registers] -to [all_outputs]
657
+ } else {
658
+ foreach clock [all_clocks] {
659
+ set clk_name [get_property $clock name]
660
+ sc_path_group -name in2reg.${clk_name} \
661
+ -from [all_inputs -no_clocks] \
662
+ -to [all_registers -clock $clock]
663
+ sc_path_group -name reg2reg.${clk_name} \
664
+ -from [all_registers -clock $clock] \
665
+ -to [all_registers -clock $clock]
666
+ sc_path_group -name reg2out.${clk_name} \
667
+ -from [all_registers -clock $clock] \
668
+ -to [all_outputs]
669
+ }
663
670
  }
664
671
  }
672
+ utl::info FLW 1 "Timing path groups: [sta::path_group_names]"
665
673
  }
666
- utl::info FLW 1 "Timing path groups: [sta::path_group_names]"
667
674
 
668
675
  # Check timing setup
669
676
  if { [sc_cfg_tool_task_check_in_list check_setup var reports] } {
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import re
3
3
  from siliconcompiler import utils
4
+ from siliconcompiler import NodeStatus
4
5
  from siliconcompiler import sc_open, SiliconCompilerError
5
6
  from siliconcompiler.tools.opensta import setup as tool_setup
6
7
  from siliconcompiler.tools.opensta import runtime_options as tool_runtime_options
@@ -28,14 +29,14 @@ def setup(chip):
28
29
 
29
30
  design = chip.top()
30
31
  if f'{design}.vg' in input_provides(chip, step, index):
31
- chip.set('tool', tool, 'task', task, 'input', f'{design}.vg',
32
+ chip.add('tool', tool, 'task', task, 'input', f'{design}.vg',
32
33
  step=step, index=index)
33
34
  else:
34
- chip.set('tool', tool, 'task', task, 'require', 'input,netlist,verilog',
35
+ chip.add('tool', tool, 'task', task, 'require', 'input,netlist,verilog',
35
36
  step=step, index=index)
36
37
 
37
38
  if f'{design}.sdc' in input_provides(chip, step, index):
38
- chip.set('tool', tool, 'task', task, 'input', f'{design}.sdc',
39
+ chip.add('tool', tool, 'task', task, 'input', f'{design}.sdc',
39
40
  step=step, index=index)
40
41
  elif chip.valid('input', 'constraint', 'sdc') and \
41
42
  chip.get('input', 'constraint', 'sdc', step=step, index=index):
@@ -84,6 +85,28 @@ def setup(chip):
84
85
  add_common_file(chip, 'opensta_generic_sdc', 'sdc/sc_constraints.sdc')
85
86
 
86
87
 
88
+ def pre_process(chip):
89
+ '''
90
+ Tool specific function to run before step execution
91
+ '''
92
+
93
+ step = chip.get('arg', 'step')
94
+ index = chip.get('arg', 'index')
95
+ tool, task = get_tool_task(chip, step, index)
96
+
97
+ # If a verilog and sdc file are both provided as input to this tool, but they
98
+ # are both empty, skip this tool step.
99
+ design = chip.top()
100
+ if (f'{design}.vg' in input_provides(chip, step, index)) and \
101
+ (f'{design}.sdc' in input_provides(chip, step, index)):
102
+ if os.path.getsize(f'inputs/{design}.vg') == 0 and \
103
+ os.path.getsize(f'inputs/{design}.sdc') == 0:
104
+ chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
105
+ chip.logger.warning(f'{step}/{index} will be skipped since no timing '
106
+ 'analysis files were provided.')
107
+ return
108
+
109
+
87
110
  def __report_map(chip, metric, basefile):
88
111
  corners = chip.getkeys('constraint', 'timing')
89
112
  mapping = {
@@ -212,5 +212,5 @@ def _diagnostics(chip, driver, compilation):
212
212
  for diag in compilation.getAllDiagnostics():
213
213
  diags.issue(diag)
214
214
 
215
- record_metric(chip, step, index, 'errors', diags.numErrors, [f'sc_{step}{index}.log'])
216
- record_metric(chip, step, index, 'warnings', diags.numWarnings, [f'sc_{step}{index}.log'])
215
+ record_metric(chip, step, index, 'errors', diags.numErrors, [f'sc_{step}_{index}.log'])
216
+ record_metric(chip, step, index, 'warnings', diags.numWarnings, [f'sc_{step}_{index}.log'])
File without changes
@@ -0,0 +1,53 @@
1
+ import os
2
+ from siliconcompiler.tools._common import add_require_input, get_tool_task, input_provides
3
+
4
+
5
+ def setup(chip):
6
+ '''
7
+ Show a VCD file.
8
+ '''
9
+ step = chip.get('arg', 'step')
10
+ index = chip.get('arg', 'index')
11
+ tool, task = get_tool_task(chip, step, index)
12
+
13
+ # Standard setup
14
+ chip.set('tool', tool, 'exe', tool)
15
+ chip.set('tool', tool, 'vswitch', '--version')
16
+ chip.set('tool', tool, 'version', '>=0.3.0', clobber=False)
17
+
18
+ # Require VCD file
19
+ if f'{chip.top()}.vcd' in input_provides(chip, step, index):
20
+ chip.set('tool', tool, 'task', task, 'input', f'{chip.top()}.vcd',
21
+ step=step, index=index)
22
+ elif chip.valid('tool', tool, 'task', task, 'var', 'show_filepath') and \
23
+ chip.get('tool', tool, 'task', task, 'var', 'show_filepath', step=step, index=index):
24
+ chip.add('tool', tool, 'task', task, 'require',
25
+ ','.join(['tool', tool, 'task', task, 'var', 'show_filepath']),
26
+ step=step, index=index)
27
+ else:
28
+ add_require_input(chip, 'input', 'waveform', 'vcd')
29
+
30
+ # Don't exit on show
31
+ chip.set('tool', tool, 'task', task, 'var', 'show_exit', False,
32
+ step=step, index=index, clobber=False)
33
+
34
+
35
+ def runtime_options(chip):
36
+ step = chip.get('arg', 'step')
37
+ index = chip.get('arg', 'index')
38
+ tool, task = get_tool_task(chip, step, index)
39
+
40
+ options = []
41
+
42
+ # Get VCD file
43
+ if os.path.exists(f'inputs/{chip.top()}.vcd'):
44
+ dump = f'inputs/{chip.top()}.vcd'
45
+ elif chip.valid('tool', tool, 'task', task, 'var', 'show_filepath') and \
46
+ chip.get('tool', tool, 'task', task, 'var', 'show_filepath', step=step, index=index):
47
+ dump = chip.get('tool', tool, 'task', task, 'var', 'show_filepath',
48
+ step=step, index=index)[0]
49
+ else:
50
+ dump = chip.find_files('input', 'waveform', 'vcd', step=step, index=index)[0]
51
+ options.append(dump)
52
+
53
+ return options
@@ -0,0 +1,30 @@
1
+ '''
2
+ Surfer is a waveform viewer with a focus on a snappy usable
3
+ interface and extensibility.
4
+
5
+ Documentation: https://gitlab.com/surfer-project/surfer/-/wikis/home
6
+
7
+ Sources: https://gitlab.com/surfer-project/surfer
8
+
9
+ Installation: https://gitlab.com/surfer-project/surfer#installation
10
+ '''
11
+
12
+
13
+ ####################################################################
14
+ # Make Docs
15
+ ####################################################################
16
+ def make_docs(chip):
17
+ from siliconcompiler.tools.surfer import show
18
+ show.setup(chip)
19
+ return chip
20
+
21
+
22
+ def parse_version(stdout):
23
+ # surfer 0.3.0
24
+ return stdout.strip().split()[1]
25
+
26
+
27
+ ####################################################################
28
+ if __name__ == "__main__":
29
+ chip = make_docs()
30
+ chip.write_manifest("surfer.json")
@@ -44,6 +44,48 @@ def setup(chip, clobber=True):
44
44
  chip.add('tool', tool, 'task', task, 'output', design + '.net', step=step, index=index)
45
45
  chip.add('tool', tool, 'task', task, 'output', design + '.place', step=step, index=index)
46
46
 
47
+ # Add a parameter for generating a post-implementation netlist for external
48
+ # static timing analysis.
49
+ if vpr.use_timing_analysis(chip):
50
+ chip.set('tool', tool, 'task', task, 'var', 'gen_post_implementation_netlist',
51
+ True, step=step, index=index, clobber=False)
52
+ else:
53
+ chip.set('tool', tool, 'task', task, 'var', 'gen_post_implementation_netlist',
54
+ False, step=step, index=index, clobber=False)
55
+
56
+ chip.set('tool', tool, 'task', task, 'var', 'gen_post_implementation_netlist',
57
+ 'set to true to have VPR generate a post-implementation netlist',
58
+ field='help')
59
+
60
+ chip.set('tool', tool, 'task', task, 'require',
61
+ ",".join(['tool', tool, 'task', task, 'var', 'gen_post_implementation_netlist']),
62
+ step=step, index=index)
63
+
64
+ # Add a parameter to control the timing corner used when generating SDF files.
65
+ chip.set('tool', tool, 'task', task, 'var', 'timing_corner', 'typical',
66
+ step=step, index=index, clobber=False)
67
+
68
+ chip.set('tool', tool, 'task', task, 'var', 'timing_corner',
69
+ 'set the timing corner for files generated by the post-implementation netlist',
70
+ field='help')
71
+
72
+ chip.set('tool', tool, 'task', task, 'require',
73
+ ",".join(['tool', tool, 'task', task, 'var', 'timing_corner']),
74
+ step=step, index=index)
75
+
76
+ # Add the post-implementation timing netlist outputs for the timing step.
77
+ # These files must always be generated so nodes that are connected after this
78
+ # step that are expecting these files do not complain if they are not generated.
79
+ timing_corner = chip.get('tool', tool, 'task', task, 'var', 'timing_corner',
80
+ step=step, index=index)[0]
81
+
82
+ chip.add('tool', tool, 'task', task, 'output', f'{design}.vg',
83
+ step=step, index=index)
84
+ chip.add('tool', tool, 'task', task, 'output', f'{design}.sdc',
85
+ step=step, index=index)
86
+ chip.add('tool', tool, 'task', task, 'output', f'{design}.{timing_corner}.sdf',
87
+ step=step, index=index)
88
+
47
89
 
48
90
  def runtime_options(chip):
49
91
  '''Command line options to vpr for the route step
@@ -104,6 +146,21 @@ def runtime_options(chip):
104
146
  options.append("--graphics_commands")
105
147
  options.append(graphics_command_str)
106
148
 
149
+ # Generate a post-implementation netlist for use in external timing analysis
150
+ # if requested.
151
+ gen_post_implementation_netlist = chip.get('tool', tool, 'task', task, 'var',
152
+ 'gen_post_implementation_netlist',
153
+ step=step, index=index)[0]
154
+ if gen_post_implementation_netlist == 'true':
155
+ # Generate the netlist.
156
+ options.extend(["--gen_post_synthesis_netlist", "on"])
157
+ # Generate the SDC file.
158
+ options.extend(["--gen_post_implementation_sdc", "on"])
159
+ # Create undriven nets for unconnected inputs.
160
+ options.extend(["--post_synth_netlist_unconn_inputs", "nets"])
161
+ # Turn off module parameters.
162
+ options.extend(["--post_synth_netlist_module_parameters", "off"])
163
+
107
164
  return options
108
165
 
109
166
 
@@ -122,3 +179,28 @@ def post_process(chip):
122
179
  shutil.copy2(f'inputs/{design}.blif', 'outputs')
123
180
  shutil.copy2(f'inputs/{design}.net', 'outputs')
124
181
  shutil.copy2(f'inputs/{design}.place', 'outputs')
182
+
183
+ # Copy and rename the post-implementation netlist results into the output
184
+ # directory to be used in external timing analysis.
185
+ step = chip.get('arg', 'step')
186
+ index = chip.get('arg', 'index')
187
+ tool, task = get_tool_task(chip, step, index)
188
+ gen_post_implementation_netlist = chip.get('tool', tool, 'task', task, 'var',
189
+ 'gen_post_implementation_netlist',
190
+ step=step, index=index)[0]
191
+ timing_corner = chip.get('tool', tool, 'task', task, 'var', 'timing_corner',
192
+ step=step, index=index)[0]
193
+
194
+ if vpr.use_timing_analysis(chip) and gen_post_implementation_netlist == 'true':
195
+ # These files will only exist if timing analysis is on and VPR was told
196
+ # to generate them.
197
+ shutil.move(f'{design}_post_synthesis.v', f'outputs/{design}.vg')
198
+ shutil.move(f'{design}_post_synthesis.sdc', f'outputs/{design}.sdc')
199
+ shutil.move(f'{design}_post_synthesis.sdf', f'outputs/{design}.{timing_corner}.sdf')
200
+ else:
201
+ # If timing analysis is on or we are not generating a post-implementation
202
+ # netlist, just produce blank files. These will trigger any future nodes
203
+ # that use them to skip.
204
+ open(f'outputs/{design}.vg', 'a')
205
+ open(f'outputs/{design}.sdc', 'a')
206
+ open(f'outputs/{design}.{timing_corner}.sdf', 'a')