siliconcompiler 0.34.1__py3-none-any.whl → 0.34.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siliconcompiler/__init__.py +23 -4
- siliconcompiler/__main__.py +1 -7
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +104 -23
- siliconcompiler/apps/sc.py +4 -8
- siliconcompiler/apps/sc_dashboard.py +6 -4
- siliconcompiler/apps/sc_install.py +10 -6
- siliconcompiler/apps/sc_issue.py +7 -5
- siliconcompiler/apps/sc_remote.py +1 -1
- siliconcompiler/apps/sc_server.py +9 -14
- siliconcompiler/apps/sc_show.py +7 -6
- siliconcompiler/apps/smake.py +130 -94
- siliconcompiler/apps/utils/replay.py +4 -7
- siliconcompiler/apps/utils/summarize.py +3 -5
- siliconcompiler/asic.py +420 -0
- siliconcompiler/checklist.py +25 -2
- siliconcompiler/cmdlineschema.py +534 -0
- siliconcompiler/constraints/__init__.py +17 -0
- siliconcompiler/constraints/asic_component.py +378 -0
- siliconcompiler/constraints/asic_floorplan.py +449 -0
- siliconcompiler/constraints/asic_pins.py +489 -0
- siliconcompiler/constraints/asic_timing.py +517 -0
- siliconcompiler/core.py +10 -35
- siliconcompiler/data/templates/tcl/manifest.tcl.j2 +8 -0
- siliconcompiler/dependencyschema.py +96 -202
- siliconcompiler/design.py +327 -241
- siliconcompiler/filesetschema.py +250 -0
- siliconcompiler/flowgraph.py +298 -106
- siliconcompiler/fpga.py +124 -1
- siliconcompiler/library.py +331 -0
- siliconcompiler/metric.py +327 -92
- siliconcompiler/metrics/__init__.py +7 -0
- siliconcompiler/metrics/asic.py +245 -0
- siliconcompiler/metrics/fpga.py +220 -0
- siliconcompiler/package/__init__.py +391 -67
- siliconcompiler/package/git.py +92 -16
- siliconcompiler/package/github.py +114 -22
- siliconcompiler/package/https.py +79 -16
- siliconcompiler/packageschema.py +341 -16
- siliconcompiler/pathschema.py +255 -0
- siliconcompiler/pdk.py +566 -1
- siliconcompiler/project.py +1460 -0
- siliconcompiler/record.py +38 -1
- siliconcompiler/remote/__init__.py +5 -2
- siliconcompiler/remote/client.py +11 -6
- siliconcompiler/remote/schema.py +5 -23
- siliconcompiler/remote/server.py +41 -54
- siliconcompiler/report/__init__.py +3 -3
- siliconcompiler/report/dashboard/__init__.py +48 -14
- siliconcompiler/report/dashboard/cli/__init__.py +99 -21
- siliconcompiler/report/dashboard/cli/board.py +364 -179
- siliconcompiler/report/dashboard/web/__init__.py +90 -12
- siliconcompiler/report/dashboard/web/components/__init__.py +219 -240
- siliconcompiler/report/dashboard/web/components/flowgraph.py +49 -26
- siliconcompiler/report/dashboard/web/components/graph.py +139 -100
- siliconcompiler/report/dashboard/web/layouts/__init__.py +29 -1
- siliconcompiler/report/dashboard/web/layouts/_common.py +38 -2
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph.py +39 -26
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_node_tab.py +50 -50
- siliconcompiler/report/dashboard/web/layouts/vertical_flowgraph_sac_tabs.py +49 -46
- siliconcompiler/report/dashboard/web/state.py +141 -14
- siliconcompiler/report/dashboard/web/utils/__init__.py +79 -16
- siliconcompiler/report/dashboard/web/utils/file_utils.py +74 -11
- siliconcompiler/report/dashboard/web/viewer.py +25 -1
- siliconcompiler/report/report.py +5 -2
- siliconcompiler/report/summary_image.py +29 -11
- siliconcompiler/scheduler/__init__.py +9 -1
- siliconcompiler/scheduler/docker.py +81 -4
- siliconcompiler/scheduler/run_node.py +37 -20
- siliconcompiler/scheduler/scheduler.py +211 -36
- siliconcompiler/scheduler/schedulernode.py +394 -60
- siliconcompiler/scheduler/send_messages.py +77 -29
- siliconcompiler/scheduler/slurm.py +76 -12
- siliconcompiler/scheduler/taskscheduler.py +142 -21
- siliconcompiler/schema/__init__.py +0 -4
- siliconcompiler/schema/baseschema.py +338 -59
- siliconcompiler/schema/editableschema.py +14 -6
- siliconcompiler/schema/journal.py +28 -17
- siliconcompiler/schema/namedschema.py +22 -14
- siliconcompiler/schema/parameter.py +89 -28
- siliconcompiler/schema/parametertype.py +2 -0
- siliconcompiler/schema/parametervalue.py +258 -15
- siliconcompiler/schema/safeschema.py +25 -2
- siliconcompiler/schema/schema_cfg.py +23 -19
- siliconcompiler/schema/utils.py +2 -2
- siliconcompiler/schema_obj.py +24 -5
- siliconcompiler/tool.py +1131 -265
- siliconcompiler/tools/bambu/__init__.py +41 -0
- siliconcompiler/tools/builtin/concatenate.py +2 -2
- siliconcompiler/tools/builtin/minimum.py +2 -1
- siliconcompiler/tools/builtin/mux.py +2 -1
- siliconcompiler/tools/builtin/nop.py +2 -1
- siliconcompiler/tools/builtin/verify.py +2 -1
- siliconcompiler/tools/klayout/__init__.py +95 -0
- siliconcompiler/tools/openroad/__init__.py +289 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +3 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +7 -2
- siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +8 -4
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +9 -5
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +5 -1
- siliconcompiler/tools/slang/__init__.py +1 -1
- siliconcompiler/tools/slang/elaborate.py +2 -1
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +1 -1
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +8 -1
- siliconcompiler/tools/vivado/syn_fpga.py +6 -0
- siliconcompiler/tools/vivado/vivado.py +35 -2
- siliconcompiler/tools/vpr/__init__.py +150 -0
- siliconcompiler/tools/yosys/__init__.py +369 -1
- siliconcompiler/tools/yosys/scripts/procs.tcl +0 -1
- siliconcompiler/toolscripts/_tools.json +5 -10
- siliconcompiler/utils/__init__.py +66 -0
- siliconcompiler/utils/flowgraph.py +2 -2
- siliconcompiler/utils/issue.py +2 -1
- siliconcompiler/utils/logging.py +14 -0
- siliconcompiler/utils/multiprocessing.py +256 -0
- siliconcompiler/utils/showtools.py +10 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/METADATA +6 -6
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/RECORD +122 -115
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/entry_points.txt +3 -0
- siliconcompiler/schema/cmdlineschema.py +0 -250
- siliconcompiler/schema/packageschema.py +0 -101
- siliconcompiler/toolscripts/rhel8/install-slang.sh +0 -40
- siliconcompiler/toolscripts/rhel9/install-slang.sh +0 -40
- siliconcompiler/toolscripts/ubuntu20/install-slang.sh +0 -47
- siliconcompiler/toolscripts/ubuntu22/install-slang.sh +0 -37
- siliconcompiler/toolscripts/ubuntu24/install-slang.sh +0 -37
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.3.dist-info}/top_level.txt +0 -0
siliconcompiler/packageschema.py
CHANGED
|
@@ -2,23 +2,338 @@ import os
|
|
|
2
2
|
|
|
3
3
|
import os.path
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
|
|
5
|
+
from typing import Union, Dict, List
|
|
6
|
+
|
|
7
|
+
from siliconcompiler.pathschema import PathSchema
|
|
8
|
+
from siliconcompiler.schema import BaseSchema, EditableSchema, Parameter, Scope
|
|
7
9
|
from siliconcompiler.schema.utils import trim
|
|
8
10
|
from siliconcompiler.package import Resolver
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
class PackageSchema(
|
|
13
|
+
class PackageSchema(PathSchema):
|
|
14
|
+
"""
|
|
15
|
+
A class for managing package-related schema data.
|
|
16
|
+
"""
|
|
12
17
|
def __init__(self):
|
|
18
|
+
"""
|
|
19
|
+
Initializes a PackageSchema object.
|
|
20
|
+
"""
|
|
13
21
|
super().__init__()
|
|
14
22
|
|
|
15
23
|
schema_package(self)
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
def set_description(self, desc: str):
|
|
26
|
+
"""
|
|
27
|
+
Set the description of the package.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
desc (str): The description string.
|
|
31
|
+
"""
|
|
32
|
+
return self.set("package", "description", trim(desc))
|
|
33
|
+
|
|
34
|
+
def get_description(self) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Get the description of the package.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
str: The description string.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
return self.get("package", "description")
|
|
43
|
+
|
|
44
|
+
def set_version(self, version: str):
|
|
45
|
+
"""
|
|
46
|
+
Set the version of the package.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
version (str): The version string.
|
|
50
|
+
"""
|
|
51
|
+
return self.set("package", "version", version)
|
|
52
|
+
|
|
53
|
+
def get_version(self) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Get the version of the package.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
str: The version string.
|
|
59
|
+
"""
|
|
60
|
+
return self.get("package", "version")
|
|
61
|
+
|
|
62
|
+
def set_vendor(self, vendor: str):
|
|
63
|
+
"""
|
|
64
|
+
Set the vendor of the package.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
vendor (str): The vendor name.
|
|
68
|
+
"""
|
|
69
|
+
return self.set("package", "vendor", vendor)
|
|
70
|
+
|
|
71
|
+
def get_vendor(self) -> str:
|
|
72
|
+
"""
|
|
73
|
+
Get the vendor of the package.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
str: The vendor name.
|
|
77
|
+
"""
|
|
78
|
+
return self.get("package", "vendor")
|
|
79
|
+
|
|
80
|
+
def add_license(self, name: str):
|
|
81
|
+
"""
|
|
82
|
+
Add a license name to the package.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
name (str): The name of the license.
|
|
86
|
+
"""
|
|
87
|
+
return self.add("package", "license", name)
|
|
88
|
+
|
|
89
|
+
def add_licensefile(self, file: str, dataroot: str = None):
|
|
90
|
+
"""
|
|
91
|
+
Add a license file to the package.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
file (str): The path to the license file.
|
|
95
|
+
dataroot (str, optional): The data reference for the package. Defaults to None,
|
|
96
|
+
which uses the active package.
|
|
97
|
+
"""
|
|
98
|
+
if not dataroot:
|
|
99
|
+
dataroot = self._get_active("package")
|
|
100
|
+
with self.active_dataroot(dataroot):
|
|
101
|
+
return self.add("package", "licensefile", file)
|
|
102
|
+
|
|
103
|
+
def get_license(self) -> List[str]:
|
|
104
|
+
"""
|
|
105
|
+
Get a list of license names associated with the package.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
List[str]: A list of license names.
|
|
109
|
+
"""
|
|
110
|
+
return self.get("package", "license")
|
|
111
|
+
|
|
112
|
+
def get_licensefile(self) -> List[str]:
|
|
113
|
+
"""
|
|
114
|
+
Get a list of license file paths associated with the package.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
List[str]: A list of file paths.
|
|
118
|
+
"""
|
|
119
|
+
return self.find_files("package", "licensefile")
|
|
120
|
+
|
|
121
|
+
def add_author(self,
|
|
122
|
+
identifier: str,
|
|
123
|
+
name: str = None,
|
|
124
|
+
email: str = None,
|
|
125
|
+
organization: str = None):
|
|
126
|
+
"""
|
|
127
|
+
Add or update author information for the package.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
identifier (str): A unique identifier for the author.
|
|
131
|
+
name (str, optional): The author's name. Defaults to None.
|
|
132
|
+
email (str, optional): The author's email address. Defaults to None.
|
|
133
|
+
organization (str, optional): The author's organization. Defaults to None.
|
|
134
|
+
"""
|
|
135
|
+
params = []
|
|
136
|
+
if name:
|
|
137
|
+
params.append(self.set("package", "author", identifier, "name", name))
|
|
138
|
+
if email:
|
|
139
|
+
params.append(self.set("package", "author", identifier, "email", email))
|
|
140
|
+
if organization:
|
|
141
|
+
params.append(self.set("package", "author", identifier, "organization", organization))
|
|
142
|
+
return [p for p in params if p]
|
|
143
|
+
|
|
144
|
+
def get_author(self, identifier: str = None):
|
|
145
|
+
"""
|
|
146
|
+
Returns the author information for a specific author or all authors.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
identifier (str): A unique identifier for the author, if None returns all
|
|
150
|
+
"""
|
|
151
|
+
if identifier is None:
|
|
152
|
+
authors = []
|
|
153
|
+
for author in self.getkeys("package", "author"):
|
|
154
|
+
authors.append(self.get_author(author))
|
|
155
|
+
return authors
|
|
156
|
+
return {
|
|
157
|
+
"name": self.get("package", "author", identifier, "name"),
|
|
158
|
+
"email": self.get("package", "author", identifier, "email"),
|
|
159
|
+
"organization": self.get("package", "author", identifier, "organization")
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
def add_doc(self, type: str, path: str, dataroot: str = None):
|
|
163
|
+
"""
|
|
164
|
+
Add documentation to the package.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
type (str): The type of documentation (e.g., "manual", "api").
|
|
168
|
+
path (str): The path to the documentation file.
|
|
169
|
+
dataroot (str, optional): The data reference for the package. Defaults to None,
|
|
170
|
+
which uses the active package.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The result of the `add` operation.
|
|
174
|
+
"""
|
|
175
|
+
if not dataroot:
|
|
176
|
+
dataroot = self._get_active("package")
|
|
177
|
+
with self.active_dataroot(dataroot):
|
|
178
|
+
return self.add("package", "doc", type, path)
|
|
179
|
+
|
|
180
|
+
def get_doc(self, type: str = None) -> Union[List[str], Dict[str, List[str]]]:
|
|
181
|
+
"""
|
|
182
|
+
Get documentation files for the package.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
type (str, optional): The type of documentation to retrieve. If None,
|
|
186
|
+
returns all documentation organized by type. Defaults to None.
|
|
187
|
+
"""
|
|
188
|
+
if type:
|
|
189
|
+
return self.find_files("package", "doc", type)
|
|
190
|
+
|
|
191
|
+
docs = {}
|
|
192
|
+
for type in self.getkeys("package", "doc"):
|
|
193
|
+
doc_files = self.find_files("package", "doc", type)
|
|
194
|
+
if doc_files:
|
|
195
|
+
docs[type] = doc_files
|
|
196
|
+
return docs
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def _getdict_type(cls) -> str:
|
|
200
|
+
"""
|
|
201
|
+
Returns the meta data for getdict
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
return PackageSchema.__name__
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
############################################
|
|
208
|
+
# Package information
|
|
209
|
+
############################################
|
|
210
|
+
def schema_package(schema):
|
|
211
|
+
"""
|
|
212
|
+
Adds package schema parameters to the given schema.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
schema (EditableSchema): The schema to modify.
|
|
216
|
+
"""
|
|
217
|
+
schema = EditableSchema(schema)
|
|
218
|
+
|
|
219
|
+
schema.insert(
|
|
220
|
+
'package', 'version',
|
|
221
|
+
Parameter(
|
|
222
|
+
'str',
|
|
223
|
+
scope=Scope.GLOBAL,
|
|
224
|
+
shorthelp="Package: version",
|
|
225
|
+
switch="-package_version <str>",
|
|
226
|
+
example=[
|
|
227
|
+
"cli: -package_version 1.0",
|
|
228
|
+
"api: chip.set('package', 'version', '1.0')"],
|
|
229
|
+
help=trim("""Package version. Can be a branch, tag, commit hash,
|
|
230
|
+
or a semver compatible version.""")))
|
|
231
|
+
|
|
232
|
+
schema.insert(
|
|
233
|
+
'package', 'vendor',
|
|
234
|
+
Parameter(
|
|
235
|
+
'str',
|
|
236
|
+
scope=Scope.GLOBAL,
|
|
237
|
+
shorthelp="Package: vendor",
|
|
238
|
+
switch="-package_vendor <str>",
|
|
239
|
+
example=[
|
|
240
|
+
"cli: -package_vendor acme",
|
|
241
|
+
"api: chip.set('package', 'vendor', 'acme')"],
|
|
242
|
+
help=trim("""Package vendor.""")))
|
|
243
|
+
|
|
244
|
+
schema.insert(
|
|
245
|
+
'package', 'description',
|
|
246
|
+
Parameter(
|
|
247
|
+
'str',
|
|
248
|
+
scope=Scope.GLOBAL,
|
|
249
|
+
shorthelp="Package: description",
|
|
250
|
+
switch="-package_description <str>",
|
|
251
|
+
example=[
|
|
252
|
+
"cli: -package_description 'Yet another cpu'",
|
|
253
|
+
"api: chip.set('package', 'description', 'Yet another cpu')"],
|
|
254
|
+
help=trim("""Package short one line description for package
|
|
255
|
+
managers and summary reports.""")))
|
|
256
|
+
|
|
257
|
+
for item in [
|
|
258
|
+
'datasheet',
|
|
259
|
+
'reference',
|
|
260
|
+
'userguide',
|
|
261
|
+
'quickstart',
|
|
262
|
+
'releasenotes',
|
|
263
|
+
'testplan',
|
|
264
|
+
'signoff',
|
|
265
|
+
'tutorial']:
|
|
266
|
+
schema.insert(
|
|
267
|
+
'package', 'doc', item,
|
|
268
|
+
Parameter(
|
|
269
|
+
'[file]',
|
|
270
|
+
scope=Scope.GLOBAL,
|
|
271
|
+
shorthelp=f"Package: {item} document",
|
|
272
|
+
switch=f"-package_doc_{item} <file>",
|
|
273
|
+
example=[
|
|
274
|
+
f"cli: -package_doc_{item} {item}.pdf",
|
|
275
|
+
f"api: chip.set('package', 'doc', '{item}', '{item}.pdf')"],
|
|
276
|
+
help=trim(f"""Package list of {item} documents.""")))
|
|
277
|
+
|
|
278
|
+
schema.insert(
|
|
279
|
+
'package', 'license',
|
|
280
|
+
Parameter(
|
|
281
|
+
'[str]',
|
|
282
|
+
scope=Scope.GLOBAL,
|
|
283
|
+
shorthelp="Package: license identifiers",
|
|
284
|
+
switch="-package_license <str>",
|
|
285
|
+
example=[
|
|
286
|
+
"cli: -package_license 'Apache-2.0'",
|
|
287
|
+
"api: chip.set('package', 'license', 'Apache-2.0')"],
|
|
288
|
+
help=trim("""Package list of SPDX license identifiers.""")))
|
|
289
|
+
|
|
290
|
+
schema.insert(
|
|
291
|
+
'package', 'licensefile',
|
|
292
|
+
Parameter(
|
|
293
|
+
'[file]',
|
|
294
|
+
scope=Scope.GLOBAL,
|
|
295
|
+
shorthelp="Package: license files",
|
|
296
|
+
switch="-package_licensefile <file>",
|
|
297
|
+
example=[
|
|
298
|
+
"cli: -package_licensefile './LICENSE'",
|
|
299
|
+
"api: chip.set('package', 'licensefile', './LICENSE')"],
|
|
300
|
+
help=trim("""Package list of license files for to be
|
|
301
|
+
applied in cases when a SPDX identifier is not available.
|
|
302
|
+
(eg. proprietary licenses).""")))
|
|
303
|
+
|
|
304
|
+
for item in [
|
|
305
|
+
'name',
|
|
306
|
+
'email',
|
|
307
|
+
'organization']:
|
|
308
|
+
schema.insert(
|
|
309
|
+
'package', 'author', 'default', item,
|
|
310
|
+
Parameter(
|
|
311
|
+
'str',
|
|
312
|
+
scope=Scope.GLOBAL,
|
|
313
|
+
shorthelp=f"Package: author {item}",
|
|
314
|
+
switch=f"-package_author_{item} 'userid <str>'",
|
|
315
|
+
example=[
|
|
316
|
+
f"cli: -package_author_{item} 'wiley wiley@acme.com'",
|
|
317
|
+
f"api: chip.set('package', 'author', 'wiley', '{item}', 'wiley@acme.com')"],
|
|
318
|
+
help=trim(f"""Package author {item} provided with full name as key and
|
|
319
|
+
{item} as value.""")))
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class PackageSchemaTmp(BaseSchema):
|
|
323
|
+
"""
|
|
324
|
+
A temporary package schema used for development and testing.
|
|
325
|
+
"""
|
|
326
|
+
def __init__(self):
|
|
327
|
+
"""
|
|
328
|
+
Initializes a temporary PackageSchemaTmp object.
|
|
329
|
+
"""
|
|
330
|
+
super().__init__()
|
|
331
|
+
|
|
332
|
+
schema_package_tmp(self)
|
|
18
333
|
|
|
19
334
|
def register(self, name, path, ref=None, clobber=True):
|
|
20
335
|
"""
|
|
21
|
-
Registers a package by its name with the source path and reference
|
|
336
|
+
Registers a package by its name with the source path and reference.
|
|
22
337
|
|
|
23
338
|
Registered package sources are stored in the package section of the schema.
|
|
24
339
|
|
|
@@ -50,40 +365,50 @@ class PackageSchema(BaseSchema):
|
|
|
50
365
|
return success
|
|
51
366
|
|
|
52
367
|
def get_resolver(self, package):
|
|
53
|
-
|
|
54
|
-
Returns a specific resolver
|
|
368
|
+
"""
|
|
369
|
+
Returns a specific resolver for a package.
|
|
55
370
|
|
|
56
371
|
Args:
|
|
57
372
|
package (str): name of package
|
|
58
|
-
|
|
373
|
+
"""
|
|
59
374
|
resolver_cls = Resolver.find_resolver(self.get("source", package, "path"))
|
|
60
375
|
resolver = resolver_cls(package, self._parent(root=True),
|
|
61
376
|
self.get("source", package, "path"),
|
|
62
377
|
self.get("source", package, "ref"))
|
|
63
|
-
resolver.set_cache(self.__cache)
|
|
64
378
|
return resolver
|
|
65
379
|
|
|
66
380
|
def get_resolvers(self):
|
|
67
|
-
|
|
381
|
+
"""
|
|
68
382
|
Returns a dictionary of packages with their resolver method.
|
|
69
|
-
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
Dict[str, callable]: A dictionary of package names mapped to their resolver methods.
|
|
386
|
+
"""
|
|
70
387
|
resolvers = {}
|
|
71
388
|
for package in self.getkeys("source"):
|
|
72
389
|
resolvers[package] = self.get_resolver(package).get_path
|
|
73
390
|
|
|
74
391
|
return resolvers
|
|
75
392
|
|
|
76
|
-
|
|
77
|
-
|
|
393
|
+
@classmethod
|
|
394
|
+
def _getdict_type(cls) -> str:
|
|
395
|
+
"""
|
|
396
|
+
Returns the meta data for getdict
|
|
397
|
+
"""
|
|
78
398
|
|
|
79
|
-
|
|
80
|
-
return self.__cache.copy()
|
|
399
|
+
return PackageSchemaTmp.__name__
|
|
81
400
|
|
|
82
401
|
|
|
83
402
|
############################################
|
|
84
403
|
# Package information
|
|
85
404
|
############################################
|
|
86
|
-
def
|
|
405
|
+
def schema_package_tmp(schema):
|
|
406
|
+
"""
|
|
407
|
+
Adds temporary package schema parameters to the given schema.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
schema (EditableSchema): The schema to modify.
|
|
411
|
+
"""
|
|
87
412
|
schema = EditableSchema(schema)
|
|
88
413
|
|
|
89
414
|
schema.insert(
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
import os.path
|
|
5
|
+
|
|
6
|
+
from siliconcompiler.schema.baseschema import BaseSchema
|
|
7
|
+
from siliconcompiler.schema.editableschema import EditableSchema
|
|
8
|
+
from siliconcompiler.schema.parameter import Parameter, Scope
|
|
9
|
+
from siliconcompiler.schema.utils import trim
|
|
10
|
+
|
|
11
|
+
from siliconcompiler.package import Resolver
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PathSchemaBase(BaseSchema):
|
|
15
|
+
'''
|
|
16
|
+
Schema extension to add simpler find_files and check_filepaths
|
|
17
|
+
'''
|
|
18
|
+
|
|
19
|
+
def find_files(self, *keypath,
|
|
20
|
+
missing_ok=False,
|
|
21
|
+
step=None, index=None):
|
|
22
|
+
"""
|
|
23
|
+
Returns absolute paths to files or directories based on the keypath
|
|
24
|
+
provided.
|
|
25
|
+
|
|
26
|
+
The keypath provided must point to a schema parameter of type file, dir,
|
|
27
|
+
or lists of either. Otherwise, it will trigger an error.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
keypath (list of str): Variable length schema key list.
|
|
31
|
+
missing_ok (bool): If True, silently return None when files aren't
|
|
32
|
+
found. If False, print an error and set the error flag.
|
|
33
|
+
step (str): Step name to access for parameters that may be specified
|
|
34
|
+
on a per-node basis.
|
|
35
|
+
index (str): Index name to access for parameters that may be specified
|
|
36
|
+
on a per-node basis.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
If keys points to a scalar entry, returns an absolute path to that
|
|
40
|
+
file/directory, or None if not found. It keys points to a list
|
|
41
|
+
entry, returns a list of either the absolute paths or None for each
|
|
42
|
+
entry, depending on whether it is found.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
>>> schema.find_files('input', 'verilog')
|
|
46
|
+
Returns a list of absolute paths to source files, as specified in
|
|
47
|
+
the schema.
|
|
48
|
+
"""
|
|
49
|
+
schema_root = self._parent(root=True)
|
|
50
|
+
cwd = getattr(schema_root, "cwd", os.getcwd())
|
|
51
|
+
collection_dir = getattr(schema_root, "collection_dir",
|
|
52
|
+
getattr(schema_root, "getcollectiondir", None))
|
|
53
|
+
if collection_dir:
|
|
54
|
+
collection_dir = collection_dir()
|
|
55
|
+
|
|
56
|
+
return super().find_files(*keypath,
|
|
57
|
+
missing_ok=missing_ok,
|
|
58
|
+
step=step, index=index,
|
|
59
|
+
collection_dir=collection_dir,
|
|
60
|
+
cwd=cwd)
|
|
61
|
+
|
|
62
|
+
def check_filepaths(self, ignore_keys=None):
|
|
63
|
+
'''
|
|
64
|
+
Verifies that paths to all files in manifest are valid.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
ignore_keys (list of keypaths): list of keypaths to ignore while checking
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
True if all file paths are valid, otherwise False.
|
|
71
|
+
'''
|
|
72
|
+
schema_root = self._parent(root=True)
|
|
73
|
+
cwd = getattr(schema_root, "cwd", os.getcwd())
|
|
74
|
+
logger = getattr(schema_root,
|
|
75
|
+
"logger",
|
|
76
|
+
logging.getLogger("siliconcompiler.check_filepaths"))
|
|
77
|
+
collection_dir = getattr(schema_root, "collection_dir",
|
|
78
|
+
getattr(schema_root, "getcollectiondir",
|
|
79
|
+
None))
|
|
80
|
+
if collection_dir:
|
|
81
|
+
collection_dir = collection_dir()
|
|
82
|
+
|
|
83
|
+
return super().check_filepaths(
|
|
84
|
+
ignore_keys=ignore_keys,
|
|
85
|
+
logger=logger,
|
|
86
|
+
collection_dir=collection_dir,
|
|
87
|
+
cwd=cwd)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class PathSchemaSimpleBase(PathSchemaBase):
|
|
91
|
+
def find_files(self, *keypath, missing_ok=False):
|
|
92
|
+
"""
|
|
93
|
+
Returns absolute paths to files or directories based on the keypath
|
|
94
|
+
provided.
|
|
95
|
+
The keypath provided must point to a schema parameter of type file, dir,
|
|
96
|
+
or lists of either. Otherwise, it will trigger an error.
|
|
97
|
+
Args:
|
|
98
|
+
keypath (list of str): Variable length schema key list.
|
|
99
|
+
missing_ok (bool): If True, silently return None when files aren't
|
|
100
|
+
found. If False, print an error and set the error flag.
|
|
101
|
+
Returns:
|
|
102
|
+
If keys points to a scalar entry, returns an absolute path to that
|
|
103
|
+
file/directory, or None if not found. It keys points to a list
|
|
104
|
+
entry, returns a list of either the absolute paths or None for each
|
|
105
|
+
entry, depending on whether it is found.
|
|
106
|
+
Examples:
|
|
107
|
+
>>> schema.find_files('input', 'verilog')
|
|
108
|
+
Returns a list of absolute paths to source files, as specified in
|
|
109
|
+
the schema.
|
|
110
|
+
"""
|
|
111
|
+
return super().find_files(*keypath,
|
|
112
|
+
missing_ok=missing_ok,
|
|
113
|
+
step=None, index=None)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class PathSchema(PathSchemaBase):
|
|
117
|
+
'''
|
|
118
|
+
Schema extension to add support for path handling with dataroots
|
|
119
|
+
'''
|
|
120
|
+
|
|
121
|
+
def __init__(self):
|
|
122
|
+
super().__init__()
|
|
123
|
+
|
|
124
|
+
schema = EditableSchema(self)
|
|
125
|
+
|
|
126
|
+
schema.insert(
|
|
127
|
+
'dataroot', 'default', 'path',
|
|
128
|
+
Parameter(
|
|
129
|
+
'str',
|
|
130
|
+
scope=Scope.GLOBAL,
|
|
131
|
+
shorthelp="Data directory path",
|
|
132
|
+
example=[
|
|
133
|
+
"api: chip.set('dataroot', "
|
|
134
|
+
"'freepdk45_data', 'path', 'ssh://git@github.com/siliconcompiler/freepdk45/')"],
|
|
135
|
+
help=trim("""
|
|
136
|
+
Data directory path, this points the location where the data can be
|
|
137
|
+
retrieved or accessed.
|
|
138
|
+
Allowed roots:
|
|
139
|
+
|
|
140
|
+
* /path/on/network/drive
|
|
141
|
+
* file:///path/on/network/drive
|
|
142
|
+
* git+https://github.com/xyz/xyz
|
|
143
|
+
* git://github.com/xyz/xyz
|
|
144
|
+
* git+ssh://github.com/xyz/xyz
|
|
145
|
+
* ssh://github.com/xyz/xyz
|
|
146
|
+
* https://github.com/xyz/xyz/archive
|
|
147
|
+
* https://zeroasic.com/xyz.tar.gz
|
|
148
|
+
* github://siliconcompiler/lambdapdk/v1.0/asap7.tar.gz
|
|
149
|
+
* python://siliconcompiler
|
|
150
|
+
""")))
|
|
151
|
+
|
|
152
|
+
schema.insert(
|
|
153
|
+
'dataroot', 'default', 'tag',
|
|
154
|
+
Parameter(
|
|
155
|
+
'str',
|
|
156
|
+
scope=Scope.GLOBAL,
|
|
157
|
+
shorthelp="Data directory reference tag/version",
|
|
158
|
+
example=[
|
|
159
|
+
"api: chip.set('dataroot', 'freepdk45_data', 'tag', '07ec4aa')"],
|
|
160
|
+
help=trim("""
|
|
161
|
+
Data directory reference tag. The meaning of the this tag depends on the
|
|
162
|
+
context of the path.
|
|
163
|
+
For git, this can be a tag, branch, or commit id. For https this is the version
|
|
164
|
+
of the file that will be downloaded.
|
|
165
|
+
""")))
|
|
166
|
+
|
|
167
|
+
def set_dataroot(self, name: str, path: str, tag: str = None):
|
|
168
|
+
"""
|
|
169
|
+
Registers a data directory by its name with the root and associated tag. If the path
|
|
170
|
+
provided is a file, the path recorded will be the directory the file is located in.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
name (str): Data directory name
|
|
174
|
+
path (str): Path to the root of the data directory, can be directory, git url,
|
|
175
|
+
archive url, or path to a file
|
|
176
|
+
tag (str): Reference of the sources, can be commitid, branch name, tag
|
|
177
|
+
|
|
178
|
+
Examples:
|
|
179
|
+
>>> schema.set_dataroot('siliconcompiler_data',
|
|
180
|
+
'git+https://github.com/siliconcompiler/siliconcompiler',
|
|
181
|
+
'v1.0.0')
|
|
182
|
+
Records the data directory for siliconcompiler_data as a git clone for tag v1.0.0
|
|
183
|
+
>>> schema.set_dataroot('file_data', __file__)
|
|
184
|
+
Records the data directory for file_data as the directory that __file__ is found in.
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
if os.path.isfile(path):
|
|
188
|
+
path = os.path.dirname(os.path.abspath(path))
|
|
189
|
+
|
|
190
|
+
BaseSchema.set(self, "dataroot", name, "path", path)
|
|
191
|
+
if tag:
|
|
192
|
+
BaseSchema.set(self, "dataroot", name, "tag", tag)
|
|
193
|
+
|
|
194
|
+
def get_dataroot(self, name: str) -> str:
|
|
195
|
+
"""
|
|
196
|
+
Returns absolute path to the data directory.
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
ValueError: is data directory is not found
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
name (str): name of the data directory to find.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
Path to the directory root.
|
|
206
|
+
|
|
207
|
+
Examples:
|
|
208
|
+
>>> schema.get_dataroot('siliconcompiler')
|
|
209
|
+
Returns the path to the root of the siliconcompiler data directory.
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
if not BaseSchema.valid(self, "dataroot", name):
|
|
213
|
+
raise ValueError(f"{name} is not a recognized source")
|
|
214
|
+
|
|
215
|
+
path = BaseSchema.get(self, "dataroot", name, "path")
|
|
216
|
+
tag = BaseSchema.get(self, "dataroot", name, "tag")
|
|
217
|
+
|
|
218
|
+
resolver = Resolver.find_resolver(path)
|
|
219
|
+
return resolver(name, self._parent(root=True), path, tag).get_path()
|
|
220
|
+
|
|
221
|
+
def _find_files_dataroot_resolvers(self):
|
|
222
|
+
"""
|
|
223
|
+
Returns a dictionary of path resolevrs data directory handling for find_files
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
dictionary of str to resolver mapping
|
|
227
|
+
"""
|
|
228
|
+
schema_root = self._parent(root=True)
|
|
229
|
+
resolver_map = {}
|
|
230
|
+
for dataroot in self.getkeys("dataroot"):
|
|
231
|
+
path = BaseSchema.get(self, "dataroot", dataroot, "path")
|
|
232
|
+
tag = BaseSchema.get(self, "dataroot", dataroot, "tag")
|
|
233
|
+
resolver = Resolver.find_resolver(path)
|
|
234
|
+
resolver_map[dataroot] = resolver(dataroot, schema_root, path, tag).get_path
|
|
235
|
+
return resolver_map
|
|
236
|
+
|
|
237
|
+
@contextlib.contextmanager
|
|
238
|
+
def active_dataroot(self, dataroot: str = None):
|
|
239
|
+
'''
|
|
240
|
+
Use this context to set the dataroot parameter on files and directory parameters.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
dataroot (str): name of the dataroot
|
|
244
|
+
|
|
245
|
+
Example:
|
|
246
|
+
>>> with schema.active_dataroot("lambdalib"):
|
|
247
|
+
... schema.set("file", "top.v")
|
|
248
|
+
Sets the file to top.v and associates lambdalib as the dataroot.
|
|
249
|
+
'''
|
|
250
|
+
|
|
251
|
+
if dataroot and dataroot not in self.getkeys("dataroot"):
|
|
252
|
+
raise ValueError(f"{dataroot} is not a recognized dataroot")
|
|
253
|
+
|
|
254
|
+
with self._active(package=dataroot):
|
|
255
|
+
yield
|