siliconcompiler 0.32.3__py3-none-any.whl → 0.33.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 (154) hide show
  1. siliconcompiler/__init__.py +19 -2
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc.py +2 -2
  4. siliconcompiler/apps/sc_install.py +3 -3
  5. siliconcompiler/apps/sc_issue.py +1 -1
  6. siliconcompiler/apps/sc_remote.py +4 -4
  7. siliconcompiler/apps/sc_show.py +2 -2
  8. siliconcompiler/apps/utils/replay.py +5 -3
  9. siliconcompiler/asic.py +120 -0
  10. siliconcompiler/checklist.py +150 -0
  11. siliconcompiler/core.py +267 -289
  12. siliconcompiler/flowgraph.py +803 -515
  13. siliconcompiler/fpga.py +84 -0
  14. siliconcompiler/metric.py +420 -0
  15. siliconcompiler/optimizer/vizier.py +2 -3
  16. siliconcompiler/package/__init__.py +29 -6
  17. siliconcompiler/pdk.py +415 -0
  18. siliconcompiler/record.py +449 -0
  19. siliconcompiler/remote/client.py +6 -3
  20. siliconcompiler/remote/schema.py +116 -112
  21. siliconcompiler/remote/server.py +3 -5
  22. siliconcompiler/report/dashboard/cli/__init__.py +13 -722
  23. siliconcompiler/report/dashboard/cli/board.py +895 -0
  24. siliconcompiler/report/dashboard/web/__init__.py +10 -10
  25. siliconcompiler/report/dashboard/web/components/__init__.py +5 -4
  26. siliconcompiler/report/dashboard/web/components/flowgraph.py +3 -3
  27. siliconcompiler/report/dashboard/web/components/graph.py +6 -3
  28. siliconcompiler/report/dashboard/web/state.py +1 -1
  29. siliconcompiler/report/dashboard/web/utils/__init__.py +4 -3
  30. siliconcompiler/report/html_report.py +2 -3
  31. siliconcompiler/report/report.py +13 -7
  32. siliconcompiler/report/summary_image.py +1 -1
  33. siliconcompiler/report/summary_table.py +3 -3
  34. siliconcompiler/report/utils.py +11 -10
  35. siliconcompiler/scheduler/__init__.py +145 -280
  36. siliconcompiler/scheduler/run_node.py +2 -1
  37. siliconcompiler/scheduler/send_messages.py +4 -4
  38. siliconcompiler/scheduler/slurm.py +2 -2
  39. siliconcompiler/schema/__init__.py +19 -2
  40. siliconcompiler/schema/baseschema.py +493 -0
  41. siliconcompiler/schema/cmdlineschema.py +250 -0
  42. siliconcompiler/{sphinx_ext → schema/docs}/__init__.py +3 -1
  43. siliconcompiler/{sphinx_ext → schema/docs}/dynamicgen.py +63 -81
  44. siliconcompiler/{sphinx_ext → schema/docs}/schemagen.py +73 -85
  45. siliconcompiler/{sphinx_ext → schema/docs}/utils.py +12 -13
  46. siliconcompiler/schema/editableschema.py +136 -0
  47. siliconcompiler/schema/journalingschema.py +238 -0
  48. siliconcompiler/schema/namedschema.py +41 -0
  49. siliconcompiler/schema/packageschema.py +101 -0
  50. siliconcompiler/schema/parameter.py +791 -0
  51. siliconcompiler/schema/parametertype.py +323 -0
  52. siliconcompiler/schema/parametervalue.py +736 -0
  53. siliconcompiler/schema/safeschema.py +37 -0
  54. siliconcompiler/schema/schema_cfg.py +109 -1789
  55. siliconcompiler/schema/utils.py +5 -68
  56. siliconcompiler/schema_obj.py +119 -0
  57. siliconcompiler/tool.py +1308 -0
  58. siliconcompiler/tools/_common/__init__.py +6 -10
  59. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +1 -1
  60. siliconcompiler/tools/bluespec/convert.py +7 -7
  61. siliconcompiler/tools/builtin/_common.py +1 -1
  62. siliconcompiler/tools/builtin/concatenate.py +2 -2
  63. siliconcompiler/tools/builtin/minimum.py +1 -1
  64. siliconcompiler/tools/builtin/mux.py +2 -1
  65. siliconcompiler/tools/builtin/nop.py +1 -1
  66. siliconcompiler/tools/builtin/verify.py +6 -4
  67. siliconcompiler/tools/chisel/convert.py +4 -4
  68. siliconcompiler/tools/genfasm/bitstream.py +3 -3
  69. siliconcompiler/tools/ghdl/convert.py +1 -1
  70. siliconcompiler/tools/icarus/compile.py +4 -4
  71. siliconcompiler/tools/icepack/bitstream.py +6 -1
  72. siliconcompiler/tools/klayout/convert_drc_db.py +5 -0
  73. siliconcompiler/tools/klayout/klayout_export.py +0 -1
  74. siliconcompiler/tools/klayout/klayout_utils.py +3 -10
  75. siliconcompiler/tools/nextpnr/apr.py +6 -1
  76. siliconcompiler/tools/nextpnr/nextpnr.py +4 -4
  77. siliconcompiler/tools/openroad/_apr.py +13 -0
  78. siliconcompiler/tools/openroad/rdlroute.py +3 -3
  79. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +1 -1
  80. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +5 -5
  81. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +2 -2
  82. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -2
  83. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +2 -2
  84. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -2
  85. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +2 -2
  86. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +2 -2
  87. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +2 -2
  88. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +2 -2
  89. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -2
  90. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +2 -2
  91. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +3 -3
  92. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +2 -2
  93. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +2 -2
  94. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +2 -2
  95. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +2 -2
  96. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +2 -2
  97. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +2 -2
  98. siliconcompiler/tools/openroad/scripts/common/procs.tcl +57 -1
  99. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +2 -2
  100. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -3
  101. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +1 -1
  102. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -3
  103. siliconcompiler/tools/openroad/scripts/sc_show.tcl +6 -6
  104. siliconcompiler/tools/slang/__init__.py +10 -10
  105. siliconcompiler/tools/surelog/parse.py +4 -4
  106. siliconcompiler/tools/sv2v/convert.py +20 -3
  107. siliconcompiler/tools/verilator/compile.py +2 -2
  108. siliconcompiler/tools/verilator/verilator.py +3 -3
  109. siliconcompiler/tools/vpr/place.py +1 -1
  110. siliconcompiler/tools/vpr/route.py +4 -4
  111. siliconcompiler/tools/vpr/screenshot.py +1 -1
  112. siliconcompiler/tools/vpr/show.py +5 -5
  113. siliconcompiler/tools/vpr/vpr.py +24 -24
  114. siliconcompiler/tools/xdm/convert.py +2 -2
  115. siliconcompiler/tools/xyce/simulate.py +1 -1
  116. siliconcompiler/tools/yosys/sc_synth_asic.tcl +74 -68
  117. siliconcompiler/tools/yosys/syn_asic.py +2 -2
  118. siliconcompiler/toolscripts/_tools.json +7 -7
  119. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +0 -2
  120. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +0 -2
  121. siliconcompiler/utils/__init__.py +8 -112
  122. siliconcompiler/utils/flowgraph.py +339 -0
  123. siliconcompiler/{issue.py → utils/issue.py} +4 -3
  124. siliconcompiler/utils/logging.py +1 -2
  125. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/METADATA +9 -8
  126. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/RECORD +151 -134
  127. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/WHEEL +1 -1
  128. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/entry_points.txt +8 -8
  129. siliconcompiler/schema/schema_obj.py +0 -1936
  130. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +0 -29
  131. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +0 -61
  132. /siliconcompiler/{templates → data/templates}/__init__.py +0 -0
  133. /siliconcompiler/{templates → data/templates}/email/__init__.py +0 -0
  134. /siliconcompiler/{templates → data/templates}/email/general.j2 +0 -0
  135. /siliconcompiler/{templates → data/templates}/email/summary.j2 +0 -0
  136. /siliconcompiler/{templates → data/templates}/issue/README.txt +0 -0
  137. /siliconcompiler/{templates → data/templates}/issue/__init__.py +0 -0
  138. /siliconcompiler/{templates → data/templates}/issue/run.sh +0 -0
  139. /siliconcompiler/{templates → data/templates}/replay/replay.py.j2 +0 -0
  140. /siliconcompiler/{templates → data/templates}/replay/replay.sh.j2 +0 -0
  141. /siliconcompiler/{templates → data/templates}/replay/requirements.txt +0 -0
  142. /siliconcompiler/{templates → data/templates}/replay/setup.sh +0 -0
  143. /siliconcompiler/{templates → data/templates}/report/__init__.py +0 -0
  144. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.css +0 -0
  145. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.js +0 -0
  146. /siliconcompiler/{templates → data/templates}/report/bootstrap_LICENSE.md +0 -0
  147. /siliconcompiler/{templates → data/templates}/report/sc_report.j2 +0 -0
  148. /siliconcompiler/{templates → data/templates}/slurm/__init__.py +0 -0
  149. /siliconcompiler/{templates → data/templates}/slurm/run.sh +0 -0
  150. /siliconcompiler/{templates → data/templates}/tcl/__init__.py +0 -0
  151. /siliconcompiler/{templates → data/templates}/tcl/manifest.tcl.j2 +0 -0
  152. /siliconcompiler/{units.py → utils/units.py} +0 -0
  153. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/licenses/LICENSE +0 -0
  154. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,84 @@
1
+ from siliconcompiler.schema import BaseSchema
2
+ from siliconcompiler.schema import EditableSchema, Parameter, Scope
3
+ from siliconcompiler.schema.utils import trim
4
+
5
+
6
+ class FPGASchema(BaseSchema):
7
+ def __init__(self):
8
+ super().__init__()
9
+
10
+ schema_fpga(self)
11
+
12
+
13
+ ###############################################################################
14
+ # FPGA
15
+ ###############################################################################
16
+ def schema_fpga(schema):
17
+ schema = EditableSchema(schema)
18
+
19
+ partname = 'default'
20
+ key = 'default'
21
+
22
+ schema.insert(
23
+ 'partname',
24
+ Parameter(
25
+ 'str',
26
+ scope=Scope.GLOBAL,
27
+ shorthelp="FPGA: part name",
28
+ switch="-fpga_partname <str>",
29
+ example=["cli: -fpga_partname fpga64k",
30
+ "api: chip.set('fpga', 'partname', 'fpga64k')"],
31
+ help=trim("""
32
+ Complete part name used as a device target by the FPGA compilation
33
+ tool. The part name must be an exact string match to the partname
34
+ hard coded within the FPGA EDA tool.""")))
35
+
36
+ schema.insert(
37
+ partname, 'vendor',
38
+ Parameter(
39
+ 'str',
40
+ scope=Scope.GLOBAL,
41
+ shorthelp="FPGA: vendor name",
42
+ switch="-fpga_vendor 'partname <str>'",
43
+ example=["cli: -fpga_vendor 'fpga64k acme'",
44
+ "api: chip.set('fpga', 'fpga64k', 'vendor', 'acme')"],
45
+ help=trim("""
46
+ Name of the FPGA vendor for the FPGA partname.""")))
47
+
48
+ schema.insert(
49
+ partname, 'lutsize',
50
+ Parameter(
51
+ 'int',
52
+ scope=Scope.GLOBAL,
53
+ shorthelp="FPGA: lutsize",
54
+ switch="-fpga_lutsize 'partname <int>'",
55
+ example=["cli: -fpga_lutsize 'fpga64k 4'",
56
+ "api: chip.set('fpga', 'fpga64k', 'lutsize', '4')"],
57
+ help=trim("""
58
+ Specify the number of inputs in each lookup table (LUT) for the
59
+ FPGA partname. For architectures with fracturable LUTs, this is
60
+ the number of inputs of the unfractured LUT.""")))
61
+
62
+ schema.insert(
63
+ partname, 'file', key,
64
+ Parameter(
65
+ '[file]',
66
+ scope=Scope.GLOBAL,
67
+ shorthelp="FPGA: file",
68
+ switch="-fpga_file 'partname key <file>'",
69
+ example=["cli: -fpga_file 'fpga64k archfile my_arch.xml'",
70
+ "api: chip.set('fpga', 'fpga64k', 'file', 'archfile', 'my_arch.xml')"],
71
+ help=trim("""
72
+ Specify a file for the FPGA partname.""")))
73
+
74
+ schema.insert(
75
+ partname, 'var', key,
76
+ Parameter(
77
+ '[str]',
78
+ scope=Scope.GLOBAL,
79
+ shorthelp="FPGA: var",
80
+ switch="-fpga_var 'partname key <str>'",
81
+ example=["cli: -fpga_var 'fpga64k channelwidth 100'",
82
+ "api: chip.set('fpga', 'fpga64k', 'var', 'channelwidth', '100')"],
83
+ help=trim("""
84
+ Specify a variable value for the FPGA partname.""")))
@@ -0,0 +1,420 @@
1
+ from siliconcompiler.schema import BaseSchema
2
+ from siliconcompiler.schema import EditableSchema, Parameter, PerNode, Scope
3
+ from siliconcompiler.schema.utils import trim
4
+
5
+ from siliconcompiler.utils.units import convert
6
+
7
+
8
+ class MetricSchema(BaseSchema):
9
+ def __init__(self):
10
+ super().__init__()
11
+
12
+ schema_metric(self)
13
+
14
+ def clear(self, step, index):
15
+ '''
16
+ Clear all saved metrics for a given step and index
17
+
18
+ Args:
19
+ step (str): Step name to clear.
20
+ index (str/int): Index name to clear.
21
+ '''
22
+ for metric in self.getkeys():
23
+ self.unset(metric, step=step, index=str(index))
24
+
25
+ def record(self, step, index, metric, value, unit=None):
26
+ """
27
+ Record a metric
28
+
29
+ Args:
30
+ step (str): step to record
31
+ index (str/int): index to record
32
+ metric (str): name of metric
33
+ value (int/float): value to record
34
+ unit (str): unit associated with value
35
+ """
36
+ metric_unit = self.get(metric, field='unit')
37
+
38
+ if not metric_unit and unit:
39
+ raise ValueError(f"{metric} does not have a unit, but {unit} was supplied")
40
+
41
+ if metric_unit:
42
+ value = convert(value, from_unit=unit, to_unit=metric_unit)
43
+
44
+ return self.set(metric, value, step=step, index=str(index))
45
+
46
+
47
+ ###########################################################################
48
+ # Metrics to Track
49
+ ###########################################################################
50
+ def schema_metric(schema):
51
+ schema = EditableSchema(schema)
52
+
53
+ metrics = {'errors': 'errors',
54
+ 'warnings': 'warnings',
55
+ 'drvs': 'design rule violations',
56
+ 'drcs': 'physical design rule violations',
57
+ 'unconstrained': 'unconstrained timing paths'}
58
+
59
+ for item, description in metrics.items():
60
+ schema.insert(
61
+ item,
62
+ Parameter(
63
+ 'int',
64
+ scope=Scope.JOB,
65
+ shorthelp=f"Metric: total {item}",
66
+ switch=f"-metric_{item} 'step index <int>'",
67
+ example=[
68
+ f"cli: -metric_{item} 'dfm 0 0'",
69
+ f"api: chip.set('metric', '{item}', 0, step='dfm', index=0)"],
70
+ pernode=PerNode.REQUIRED,
71
+ help=trim(f"""Metric tracking the total number of {description} on a
72
+ per step and index basis.""")))
73
+
74
+ schema.insert(
75
+ 'coverage',
76
+ Parameter(
77
+ 'float',
78
+ unit='%',
79
+ scope=Scope.JOB,
80
+ shorthelp="Metric: coverage",
81
+ switch="-metric_coverage 'step index <float>'",
82
+ example=[
83
+ "cli: -metric_coverage 'place 0 99.9'",
84
+ "api: chip.set('metric', 'coverage', 99.9, step='place', index=0)"],
85
+ pernode=PerNode.REQUIRED,
86
+ help=trim("""
87
+ Metric tracking the test coverage in the design expressed as a percentage
88
+ with 100 meaning full coverage. The meaning of the metric depends on the
89
+ task being executed. It can refer to code coverage, feature coverage,
90
+ stuck at fault coverage.""")))
91
+
92
+ schema.insert(
93
+ 'security',
94
+ Parameter(
95
+ 'float',
96
+ unit='%',
97
+ scope=Scope.JOB,
98
+ shorthelp="Metric: security",
99
+ switch="-metric_security 'step index <float>'",
100
+ example=[
101
+ "cli: -metric_security 'place 0 100'",
102
+ "api: chip.set('metric', 'security', 100, step='place', index=0)"],
103
+ pernode=PerNode.REQUIRED,
104
+ help=trim("""
105
+ Metric tracking the level of security (1/vulnerability) of the design.
106
+ A completely secure design would have a score of 100. There is no
107
+ absolute scale for the security metrics (like with power, area, etc)
108
+ so the metric will be task and tool dependent.""")))
109
+
110
+ metrics = {'luts': 'FPGA LUTs used',
111
+ 'dsps': 'FPGA DSP slices used',
112
+ 'brams': 'FPGA BRAM tiles used'}
113
+
114
+ for item, description in metrics.items():
115
+ schema.insert(
116
+ item,
117
+ Parameter(
118
+ 'int',
119
+ scope=Scope.JOB,
120
+ shorthelp=f"Metric: {description}",
121
+ switch=f"-metric_{item} 'step index <int>'",
122
+ example=[
123
+ f"cli: -metric_{item} 'place 0 100'",
124
+ f"api: chip.set('metric', '{item}', 100, step='place', index=0)"],
125
+ pernode=PerNode.REQUIRED,
126
+ help=trim(f"""
127
+ Metric tracking the total {description} used by the design as reported
128
+ by the implementation tool. There is no standardized definition
129
+ for this metric across vendors, so metric comparisons can
130
+ generally only be done between runs on identical tools and
131
+ device families.""")))
132
+
133
+ metrics = {'cellarea': 'cell area (ignoring fillers)',
134
+ 'totalarea': 'physical die area',
135
+ 'macroarea': 'macro cell area',
136
+ 'padcellarea': 'io pad cell area',
137
+ 'stdcellarea': 'standard cell area'}
138
+
139
+ for item, description in metrics.items():
140
+ schema.insert(
141
+ item,
142
+ Parameter(
143
+ 'float',
144
+ unit='um^2',
145
+ scope=Scope.JOB,
146
+ shorthelp=f"Metric: {item}",
147
+ switch=f"-metric_{item} 'step index <float>'",
148
+ example=[
149
+ f"cli: -metric_{item} 'place 0 100.00'",
150
+ f"api: chip.set('metric', '{item}', 100.00, step='place', index=0)"],
151
+ pernode=PerNode.REQUIRED,
152
+ help=trim(f"""
153
+ Metric tracking the total {description} occupied by the design.""")))
154
+
155
+ schema.insert(
156
+ 'utilization',
157
+ Parameter(
158
+ 'float',
159
+ unit='%',
160
+ scope=Scope.JOB,
161
+ shorthelp="Metric: area utilization",
162
+ switch="-metric_utilization 'step index <float>'",
163
+ example=[
164
+ "cli: -metric_utilization 'place 0 50.00'",
165
+ "api: chip.set('metric', 'utilization', 50.00, step='place', index=0)"],
166
+ pernode=PerNode.REQUIRED,
167
+ help=trim("""
168
+ Metric tracking the area utilization of the design calculated as
169
+ 100 * (cellarea/totalarea).""")))
170
+
171
+ schema.insert(
172
+ 'logicdepth',
173
+ Parameter(
174
+ 'int',
175
+ scope=Scope.JOB,
176
+ shorthelp="Metric: logic depth",
177
+ switch="-metric_logicdepth 'step index <int>'",
178
+ example=[
179
+ "cli: -metric_logicdepth 'place 0 8'",
180
+ "api: chip.set('metric', 'logicdepth', 8, step='place', index=0)"],
181
+ pernode=PerNode.REQUIRED,
182
+ help=trim("""
183
+ Metric tracking the logic depth of the design. This is determined
184
+ by the number of logic gates between the start of the critital timing
185
+ path to the end of the path.""")))
186
+
187
+ metrics = {'peakpower': 'worst case total peak power',
188
+ 'averagepower': 'average workload power',
189
+ 'leakagepower': 'leakage power with rails active but without any dynamic '
190
+ 'switching activity'}
191
+
192
+ for item, description in metrics.items():
193
+ schema.insert(
194
+ item,
195
+ Parameter(
196
+ 'float',
197
+ unit='mw',
198
+ scope=Scope.JOB,
199
+ shorthelp=f"Metric: {item}",
200
+ switch=f"-metric_{item} 'step index <float>'",
201
+ example=[
202
+ f"cli: -metric_{item} 'place 0 0.01'",
203
+ f"api: chip.set('metric', '{item}', 0.01, step='place', index=0)"],
204
+ pernode=PerNode.REQUIRED,
205
+ help=trim(f"""
206
+ Metric tracking the {description} of the design specified on a per step
207
+ and index basis. Power metric depend heavily on the method
208
+ being used for extraction: dynamic vs static, workload
209
+ specification (vcd vs saif), power models, process/voltage/temperature.
210
+ The power {item} metric tries to capture the data that would
211
+ usually be reflected inside a datasheet given the appropriate
212
+ footnote conditions.""")))
213
+
214
+ schema.insert(
215
+ 'irdrop',
216
+ Parameter(
217
+ 'float',
218
+ unit='mv',
219
+ scope=Scope.JOB,
220
+ shorthelp="Metric: peak IR drop",
221
+ switch="-metric_irdrop 'step index <float>'",
222
+ example=[
223
+ "cli: -metric_irdrop 'place 0 0.05'",
224
+ "api: chip.set('metric', 'irdrop', 0.05, step='place', index=0)"],
225
+ pernode=PerNode.REQUIRED,
226
+ help=trim("""
227
+ Metric tracking the peak IR drop in the design based on extracted
228
+ power and ground rail parasitics, library power models, and
229
+ switching activity. The switching activity calculated on a per
230
+ node basis is taken from one of three possible sources, in order
231
+ of priority: VCD file, SAIF file, 'activityfactor' parameter.""")))
232
+
233
+ metrics = {'holdpaths': 'hold',
234
+ 'setuppaths': 'setup'}
235
+
236
+ for item, description in metrics.items():
237
+ schema.insert(
238
+ item,
239
+ Parameter(
240
+ 'int',
241
+ scope=Scope.JOB,
242
+ shorthelp=f"Metric: {item}",
243
+ switch=f"-metric_{item} 'step index <int>'",
244
+ example=[
245
+ f"cli: -metric_{item} 'place 0 10'",
246
+ f"api: chip.set('metric', '{item}', 10, step='place', index=0)"],
247
+ pernode=PerNode.REQUIRED,
248
+ help=trim(f"""
249
+ Metric tracking the total number of timing paths violating {description}
250
+ constraints.""")))
251
+
252
+ metrics = {'holdslack': 'worst hold slack (positive or negative)',
253
+ 'holdwns': 'worst negative hold slack (positive values truncated to zero)',
254
+ 'holdtns': 'total negative hold slack (TNS)',
255
+ 'holdskew': 'hold clock skew',
256
+ 'setupslack': 'worst setup slack (positive or negative)',
257
+ 'setupwns': 'worst negative setup slack (positive values truncated to zero)',
258
+ 'setuptns': 'total negative setup slack (TNS)',
259
+ 'setupskew': 'setup clock skew'}
260
+
261
+ for item, description in metrics.items():
262
+ schema.insert(
263
+ item,
264
+ Parameter(
265
+ 'float',
266
+ unit='ns',
267
+ scope=Scope.JOB,
268
+ shorthelp=f"Metric: {item}",
269
+ switch=f"-metric_{item} 'step index <float>'",
270
+ example=[
271
+ f"cli: -metric_{item} 'place 0 0.01'",
272
+ f"api: chip.set('metric', '{item}', 0.01, step='place', index=0)"],
273
+ pernode=PerNode.REQUIRED,
274
+ help=trim(f"""
275
+ Metric tracking the {description} on a per step and index basis.""")))
276
+
277
+ metrics = {'fmax': 'maximum clock frequency'}
278
+
279
+ for item, description in metrics.items():
280
+ schema.insert(
281
+ item,
282
+ Parameter(
283
+ 'float',
284
+ unit='Hz',
285
+ scope=Scope.JOB,
286
+ shorthelp=f"Metric: {item}",
287
+ switch=f"-metric_{item} 'step index <float>'",
288
+ example=[
289
+ f"cli: -metric_{item} 'place 0 100e6'",
290
+ f"api: chip.set('metric', '{item}', 100e6, step='place', index=0)"],
291
+ pernode=PerNode.REQUIRED,
292
+ help=trim(f"""
293
+ Metric tracking the {description} on a per step and index basis.""")))
294
+
295
+ metrics = {'macros': 'macros',
296
+ 'cells': 'cell instances',
297
+ 'registers': 'register instances',
298
+ 'buffers': 'buffer instances',
299
+ 'inverters': 'inverter instances',
300
+ 'transistors': 'transistors',
301
+ 'pins': 'pins',
302
+ 'nets': 'nets',
303
+ 'vias': 'vias'}
304
+
305
+ for item, description in metrics.items():
306
+ schema.insert(
307
+ item,
308
+ Parameter(
309
+ 'int',
310
+ scope=Scope.JOB,
311
+ shorthelp=f"Metric: {item}",
312
+ switch=f"-metric_{item} 'step index <int>'",
313
+ example=[
314
+ f"cli: -metric_{item} 'place 0 100'",
315
+ f"api: chip.set('metric', '{item}', 50, step='place', index=0)"],
316
+ pernode=PerNode.REQUIRED,
317
+ help=trim(f"""
318
+ Metric tracking the total number of {description} in the design
319
+ on a per step and index basis.""")))
320
+
321
+ schema.insert(
322
+ 'wirelength',
323
+ Parameter(
324
+ 'float',
325
+ unit='um',
326
+ scope=Scope.JOB,
327
+ shorthelp="Metric: wirelength",
328
+ switch="-metric_wirelength 'step index <float>'",
329
+ example=[
330
+ "cli: -metric_wirelength 'place 0 100.0'",
331
+ "api: chip.set('metric', 'wirelength', 50.0, step='place', index=0)"],
332
+ pernode=PerNode.REQUIRED,
333
+ help=trim("""
334
+ Metric tracking the total wirelength of the design on a per step
335
+ and index basis.""")))
336
+
337
+ schema.insert(
338
+ 'overflow',
339
+ Parameter(
340
+ 'int',
341
+ scope=Scope.JOB,
342
+ shorthelp="Metric: overflow",
343
+ switch="-metric_overflow 'step index <int>'",
344
+ example=[
345
+ "cli: -metric_overflow 'place 0 0'",
346
+ "api: chip.set('metric', 'overflow', 50, step='place', index=0)"],
347
+ pernode=PerNode.REQUIRED,
348
+ help=trim("""
349
+ Metric tracking the total number of overflow tracks for the routing
350
+ on per step and index basis. Any non-zero number suggests an over
351
+ congested design. To analyze where the congestion is occurring
352
+ inspect the router log files for detailed per metal overflow
353
+ reporting and open up the design to find routing hotspots.""")))
354
+
355
+ schema.insert(
356
+ 'memory',
357
+ Parameter(
358
+ 'float',
359
+ unit='B',
360
+ scope=Scope.JOB,
361
+ shorthelp="Metric: memory",
362
+ switch="-metric_memory 'step index <float>'",
363
+ example=[
364
+ "cli: -metric_memory 'dfm 0 10e9'",
365
+ "api: chip.set('metric', 'memory', 10e9, step='dfm', index=0)"],
366
+ pernode=PerNode.REQUIRED,
367
+ help=trim("""
368
+ Metric tracking total peak program memory footprint on a per
369
+ step and index basis.""")))
370
+
371
+ schema.insert(
372
+ 'exetime',
373
+ Parameter(
374
+ 'float',
375
+ unit='s',
376
+ scope=Scope.JOB,
377
+ shorthelp="Metric: exetime",
378
+ switch="-metric_exetime 'step index <float>'",
379
+ example=[
380
+ "cli: -metric_exetime 'dfm 0 10.0'",
381
+ "api: chip.set('metric', 'exetime', 10.0, step='dfm', index=0)"],
382
+ pernode=PerNode.REQUIRED,
383
+ help=trim("""
384
+ Metric tracking time spent by the EDA executable :keypath:`tool,<tool>,exe` on a
385
+ per step and index basis. It does not include the SiliconCompiler
386
+ runtime overhead or time waiting for I/O operations and
387
+ inter-processor communication to complete.""")))
388
+
389
+ schema.insert(
390
+ 'tasktime',
391
+ Parameter(
392
+ 'float',
393
+ unit='s',
394
+ scope=Scope.JOB,
395
+ shorthelp="Metric: tasktime",
396
+ switch="-metric_tasktime 'step index <float>'",
397
+ example=[
398
+ "cli: -metric_tasktime 'dfm 0 10.0'",
399
+ "api: chip.set('metric', 'tasktime', 10.0, step='dfm', index=0)"],
400
+ pernode=PerNode.REQUIRED,
401
+ help=trim("""
402
+ Metric tracking the total amount of time spent on a task from
403
+ beginning to end, including data transfers and pre/post
404
+ processing.""")))
405
+
406
+ schema.insert(
407
+ 'totaltime',
408
+ Parameter(
409
+ 'float',
410
+ unit='s',
411
+ scope=Scope.JOB,
412
+ shorthelp="Metric: totaltime",
413
+ switch="-metric_totaltime 'step index <float>'",
414
+ example=[
415
+ "cli: -metric_totaltime 'dfm 0 10.0'",
416
+ "api: chip.set('metric', 'totaltime', 10.0, step='dfm', index=0)"],
417
+ pernode=PerNode.REQUIRED,
418
+ help=trim("""
419
+ Metric tracking the total amount of time spent from the beginning
420
+ of the run up to and including the current step and index.""")))
@@ -3,7 +3,6 @@ import uuid
3
3
  import math
4
4
  from siliconcompiler import Chip
5
5
  from siliconcompiler.optimizer import Optimizer
6
- from siliconcompiler.flowgraph import _get_flowgraph_nodes
7
6
 
8
7
  try:
9
8
  from vizier.service import clients as vz_clients
@@ -158,7 +157,7 @@ class VizierOptimizier(Optimizer):
158
157
  chip.graph(flow, org_flow, name=graph_name)
159
158
 
160
159
  # Complete nodes
161
- nodes = _get_flowgraph_nodes(chip, org_flow)
160
+ nodes = chip.schema.get("flowgraph", org_flow, field="schema").get_nodes()
162
161
  for step, _ in list(nodes):
163
162
  nodes.append((step, None))
164
163
  nodes = set(nodes)
@@ -168,7 +167,7 @@ class VizierOptimizier(Optimizer):
168
167
  if key[0] == 'history':
169
168
  continue
170
169
 
171
- for value, step, index in chip.schema._getvals(*key):
170
+ for value, step, index in chip.schema.get(*key, field=None).getvalues():
172
171
  node = (step, index)
173
172
 
174
173
  if node in nodes:
@@ -3,14 +3,15 @@ from urllib.parse import urlparse
3
3
  import importlib
4
4
  import re
5
5
  from siliconcompiler import SiliconCompilerError
6
- from siliconcompiler.utils import default_cache_dir, _resolve_env_vars
6
+ from siliconcompiler.utils import default_cache_dir
7
7
  import json
8
8
  from importlib.metadata import distributions, distribution
9
9
  import functools
10
10
  import time
11
11
  from pathlib import Path
12
12
 
13
- from siliconcompiler.utils import get_plugins
13
+ from siliconcompiler.utils import get_plugins, get_env_vars
14
+ from siliconcompiler.schema.parametervalue import PathNodeValue
14
15
 
15
16
 
16
17
  def get_cache_path(chip):
@@ -46,6 +47,18 @@ def _python_path_resolver(chip, package, path, ref, url, fetch):
46
47
  return path_from_python(chip, url.netloc)
47
48
 
48
49
 
50
+ def _key_path_resolver(chip, package, path, ref, url, fetch):
51
+ key = url.netloc.split(',')
52
+ if chip.get(*key, field='pernode').is_never():
53
+ paths = chip.find_files(*key)
54
+ else:
55
+ paths = chip.find_files(*key, step=chip.get('arg', 'step'), index=chip.get('arg', 'index'))
56
+
57
+ if isinstance(paths, list):
58
+ return paths[0]
59
+ return paths
60
+
61
+
49
62
  def _get_path_resolver(path):
50
63
  url = urlparse(path)
51
64
 
@@ -54,6 +67,9 @@ def _get_path_resolver(path):
54
67
  if func:
55
68
  return func, url
56
69
 
70
+ if url.scheme == "key":
71
+ return _key_path_resolver, url
72
+
57
73
  if url.scheme == "file":
58
74
  return _file_path_resolver, url
59
75
 
@@ -69,11 +85,15 @@ def _path(chip, package, fetch):
69
85
  data['path'] = chip.get('package', 'source', package, 'path')
70
86
  data['ref'] = chip.get('package', 'source', package, 'ref')
71
87
  if not data['path']:
72
- raise SiliconCompilerError(
73
- f'Could not find package source for {package} in schema. '
74
- 'You can use register_source() to add it.', chip=chip)
88
+ if package.startswith("key://"):
89
+ data['path'] = package
90
+ else:
91
+ raise SiliconCompilerError(
92
+ f'Could not find package source for {package} in schema. '
93
+ 'You can use register_source() to add it.', chip=chip)
75
94
 
76
- data['path'] = _resolve_env_vars(chip, data['path'], None, None)
95
+ env_vars = get_env_vars(chip, None, None)
96
+ data['path'] = PathNodeValue.resolve_env_vars(data['path'], envvars=env_vars)
77
97
 
78
98
  if os.path.exists(data['path']):
79
99
  # Path is already a path
@@ -102,6 +122,9 @@ def path(chip, package, fetch=True):
102
122
  if isinstance(data_path, tuple) and len(data_path) == 2:
103
123
  data_path, changed = data_path
104
124
 
125
+ if package.startswith("key://"):
126
+ return data_path
127
+
105
128
  if os.path.exists(data_path):
106
129
  if package not in chip._packages and changed:
107
130
  chip.logger.info(f'Saved {package} data to {data_path}')