siliconcompiler 0.34.0__py3-none-any.whl → 0.34.2__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 +14 -2
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/_common.py +1 -1
- siliconcompiler/apps/sc.py +1 -1
- siliconcompiler/apps/sc_issue.py +1 -1
- siliconcompiler/apps/sc_remote.py +3 -3
- siliconcompiler/apps/sc_show.py +3 -3
- siliconcompiler/apps/utils/replay.py +4 -4
- siliconcompiler/checklist.py +203 -2
- 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 +31 -249
- siliconcompiler/data/templates/email/general.j2 +3 -3
- siliconcompiler/data/templates/email/summary.j2 +1 -1
- siliconcompiler/data/templates/issue/README.txt +1 -1
- siliconcompiler/data/templates/report/sc_report.j2 +7 -7
- siliconcompiler/dependencyschema.py +10 -174
- siliconcompiler/design.py +325 -114
- siliconcompiler/flowgraph.py +63 -15
- siliconcompiler/library.py +133 -0
- siliconcompiler/metric.py +94 -72
- siliconcompiler/metrics/__init__.py +7 -0
- siliconcompiler/metrics/asic.py +245 -0
- siliconcompiler/metrics/fpga.py +220 -0
- siliconcompiler/optimizer/vizier.py +2 -2
- siliconcompiler/package/__init__.py +138 -35
- siliconcompiler/package/github.py +6 -10
- siliconcompiler/packageschema.py +256 -12
- siliconcompiler/pathschema.py +226 -0
- siliconcompiler/pdk.py +5 -5
- siliconcompiler/project.py +459 -0
- siliconcompiler/remote/client.py +18 -12
- siliconcompiler/remote/server.py +2 -2
- siliconcompiler/report/dashboard/cli/__init__.py +6 -6
- siliconcompiler/report/dashboard/cli/board.py +3 -3
- siliconcompiler/report/dashboard/web/components/__init__.py +5 -5
- siliconcompiler/report/dashboard/web/components/flowgraph.py +4 -4
- siliconcompiler/report/dashboard/web/components/graph.py +2 -2
- siliconcompiler/report/dashboard/web/state.py +1 -1
- siliconcompiler/report/dashboard/web/utils/__init__.py +5 -5
- siliconcompiler/report/html_report.py +1 -1
- siliconcompiler/report/report.py +4 -4
- siliconcompiler/report/summary_table.py +2 -2
- siliconcompiler/report/utils.py +5 -5
- siliconcompiler/scheduler/docker.py +4 -10
- siliconcompiler/scheduler/run_node.py +4 -8
- siliconcompiler/scheduler/scheduler.py +18 -24
- siliconcompiler/scheduler/schedulernode.py +161 -143
- siliconcompiler/scheduler/send_messages.py +3 -3
- siliconcompiler/scheduler/slurm.py +5 -3
- siliconcompiler/scheduler/taskscheduler.py +10 -8
- siliconcompiler/schema/__init__.py +0 -2
- siliconcompiler/schema/baseschema.py +148 -26
- siliconcompiler/schema/editableschema.py +14 -6
- siliconcompiler/schema/journal.py +23 -15
- siliconcompiler/schema/namedschema.py +30 -4
- siliconcompiler/schema/parameter.py +34 -19
- siliconcompiler/schema/parametertype.py +2 -0
- siliconcompiler/schema/parametervalue.py +198 -15
- siliconcompiler/schema/schema_cfg.py +18 -14
- siliconcompiler/schema_obj.py +5 -3
- siliconcompiler/tool.py +591 -179
- siliconcompiler/tools/__init__.py +2 -0
- siliconcompiler/tools/builtin/_common.py +5 -5
- siliconcompiler/tools/builtin/concatenate.py +5 -5
- siliconcompiler/tools/builtin/minimum.py +4 -4
- siliconcompiler/tools/builtin/mux.py +4 -4
- siliconcompiler/tools/builtin/nop.py +4 -4
- siliconcompiler/tools/builtin/verify.py +7 -7
- siliconcompiler/tools/execute/exec_input.py +1 -1
- siliconcompiler/tools/genfasm/genfasm.py +1 -6
- siliconcompiler/tools/openroad/_apr.py +5 -1
- siliconcompiler/tools/openroad/antenna_repair.py +1 -1
- siliconcompiler/tools/openroad/macro_placement.py +1 -1
- siliconcompiler/tools/openroad/power_grid.py +1 -1
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +5 -0
- siliconcompiler/tools/opensta/timing.py +26 -3
- siliconcompiler/tools/slang/__init__.py +2 -2
- siliconcompiler/tools/surfer/__init__.py +0 -0
- siliconcompiler/tools/surfer/show.py +53 -0
- siliconcompiler/tools/surfer/surfer.py +30 -0
- siliconcompiler/tools/vpr/route.py +27 -14
- siliconcompiler/tools/vpr/vpr.py +23 -6
- siliconcompiler/tools/yosys/__init__.py +1 -1
- siliconcompiler/tools/yosys/scripts/procs.tcl +143 -0
- siliconcompiler/tools/yosys/{sc_synth_asic.tcl → scripts/sc_synth_asic.tcl} +4 -0
- siliconcompiler/tools/yosys/{sc_synth_fpga.tcl → scripts/sc_synth_fpga.tcl} +24 -77
- siliconcompiler/tools/yosys/syn_fpga.py +14 -0
- siliconcompiler/toolscripts/_tools.json +9 -13
- siliconcompiler/toolscripts/rhel9/install-vpr.sh +0 -2
- siliconcompiler/toolscripts/ubuntu22/install-surfer.sh +33 -0
- siliconcompiler/toolscripts/ubuntu24/install-surfer.sh +33 -0
- siliconcompiler/utils/__init__.py +2 -1
- siliconcompiler/utils/flowgraph.py +24 -23
- siliconcompiler/utils/issue.py +23 -29
- siliconcompiler/utils/logging.py +35 -6
- siliconcompiler/utils/showtools.py +6 -1
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +15 -25
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +109 -97
- siliconcompiler/schema/packageschema.py +0 -101
- siliconcompiler/tools/yosys/procs.tcl +0 -71
- siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +0 -68
- siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +0 -68
- siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +0 -68
- /siliconcompiler/tools/yosys/{sc_lec.tcl → scripts/sc_lec.tcl} +0 -0
- /siliconcompiler/tools/yosys/{sc_screenshot.tcl → scripts/sc_screenshot.tcl} +0 -0
- /siliconcompiler/tools/yosys/{syn_strategies.tcl → scripts/syn_strategies.tcl} +0 -0
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
import functools
|
|
3
|
+
import hashlib
|
|
3
4
|
import importlib
|
|
4
5
|
import json
|
|
5
6
|
import logging
|
|
6
7
|
import os
|
|
8
|
+
import random
|
|
7
9
|
import re
|
|
8
10
|
import time
|
|
9
11
|
import threading
|
|
12
|
+
import uuid
|
|
10
13
|
|
|
11
14
|
import os.path
|
|
12
15
|
|
|
@@ -50,13 +53,16 @@ class Resolver:
|
|
|
50
53
|
_RESOLVERS_LOCK = threading.Lock()
|
|
51
54
|
_RESOLVERS = {}
|
|
52
55
|
|
|
56
|
+
__CACHE_LOCK = threading.Lock()
|
|
57
|
+
__CACHE = {}
|
|
58
|
+
|
|
53
59
|
def __init__(self, name, root, source, reference=None):
|
|
54
60
|
self.__name = name
|
|
55
61
|
self.__root = root
|
|
56
62
|
self.__source = source
|
|
57
63
|
self.__reference = reference
|
|
58
64
|
self.__changed = False
|
|
59
|
-
self.
|
|
65
|
+
self.__cacheid = None
|
|
60
66
|
|
|
61
67
|
if self.__root and hasattr(self.__root, "logger"):
|
|
62
68
|
self.__logger = self.__root.logger.getChild(f"resolver-{self.name}")
|
|
@@ -126,34 +132,80 @@ class Resolver:
|
|
|
126
132
|
return self.urlparse.netloc
|
|
127
133
|
|
|
128
134
|
@property
|
|
129
|
-
def changed(self):
|
|
135
|
+
def changed(self) -> bool:
|
|
130
136
|
change = self.__changed
|
|
131
137
|
self.__changed = False
|
|
132
138
|
return change
|
|
133
139
|
|
|
140
|
+
@property
|
|
141
|
+
def cache_id(self) -> str:
|
|
142
|
+
if self.__cacheid is None:
|
|
143
|
+
hash = hashlib.sha1()
|
|
144
|
+
hash.update(self.__source.encode())
|
|
145
|
+
if self.__reference:
|
|
146
|
+
hash.update(self.__reference.encode())
|
|
147
|
+
else:
|
|
148
|
+
hash.update("".encode())
|
|
149
|
+
|
|
150
|
+
self.__cacheid = hash.hexdigest()
|
|
151
|
+
return self.__cacheid
|
|
152
|
+
|
|
134
153
|
def set_changed(self):
|
|
135
154
|
self.__changed = True
|
|
136
155
|
|
|
137
|
-
def set_cache(self, cache):
|
|
138
|
-
self.__cache = cache
|
|
139
|
-
|
|
140
156
|
def resolve(self):
|
|
141
157
|
raise NotImplementedError("child class must implement this")
|
|
142
158
|
|
|
159
|
+
@staticmethod
|
|
160
|
+
def __get_root_id(root):
|
|
161
|
+
STORAGE = "__Resolver_cache_id"
|
|
162
|
+
if not getattr(root, STORAGE, None):
|
|
163
|
+
setattr(root, STORAGE, uuid.uuid4().hex)
|
|
164
|
+
return getattr(root, STORAGE)
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def get_cache(root, name: str = None):
|
|
168
|
+
with Resolver.__CACHE_LOCK:
|
|
169
|
+
root_id = Resolver.__get_root_id(root)
|
|
170
|
+
if root_id not in Resolver.__CACHE:
|
|
171
|
+
Resolver.__CACHE[root_id] = {}
|
|
172
|
+
|
|
173
|
+
if name:
|
|
174
|
+
return Resolver.__CACHE[root_id].get(name, None)
|
|
175
|
+
|
|
176
|
+
return Resolver.__CACHE[root_id].copy()
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def set_cache(root, name: str, path: str):
|
|
180
|
+
with Resolver.__CACHE_LOCK:
|
|
181
|
+
root_id = Resolver.__get_root_id(root)
|
|
182
|
+
if root_id not in Resolver.__CACHE:
|
|
183
|
+
Resolver.__CACHE[root_id] = {}
|
|
184
|
+
Resolver.__CACHE[root_id][name] = path
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def reset_cache(root):
|
|
188
|
+
with Resolver.__CACHE_LOCK:
|
|
189
|
+
root_id = Resolver.__get_root_id(root)
|
|
190
|
+
if root_id in Resolver.__CACHE:
|
|
191
|
+
del Resolver.__CACHE[root_id]
|
|
192
|
+
|
|
143
193
|
def get_path(self):
|
|
144
|
-
|
|
145
|
-
|
|
194
|
+
cache_path = Resolver.get_cache(self.__root, self.cache_id)
|
|
195
|
+
if cache_path:
|
|
196
|
+
return cache_path
|
|
146
197
|
|
|
147
198
|
path = self.resolve()
|
|
148
199
|
if not os.path.exists(path):
|
|
149
200
|
raise FileNotFoundError(f"Unable to locate {self.name} at {path}")
|
|
150
201
|
|
|
151
|
-
if self.changed
|
|
202
|
+
if self.changed:
|
|
152
203
|
self.logger.info(f'Saved {self.name} data to {path}')
|
|
153
204
|
else:
|
|
154
205
|
self.logger.info(f'Found {self.name} data at {path}')
|
|
155
|
-
|
|
156
|
-
|
|
206
|
+
|
|
207
|
+
Resolver.set_cache(self.__root, self.cache_id, path)
|
|
208
|
+
return path
|
|
157
209
|
|
|
158
210
|
def __resolve_env(self, path):
|
|
159
211
|
env_save = os.environ.copy()
|
|
@@ -198,6 +250,7 @@ class RemoteResolver(Resolver):
|
|
|
198
250
|
if not root:
|
|
199
251
|
return Path(default_path)
|
|
200
252
|
|
|
253
|
+
path = None
|
|
201
254
|
if root.valid('option', 'cachedir'):
|
|
202
255
|
path = root.get('option', 'cachedir')
|
|
203
256
|
if path:
|
|
@@ -249,32 +302,51 @@ class RemoteResolver(Resolver):
|
|
|
249
302
|
return RemoteResolver._CACHE_LOCKS[self.name]
|
|
250
303
|
|
|
251
304
|
@contextlib.contextmanager
|
|
252
|
-
def
|
|
305
|
+
def __thread_lock(self):
|
|
253
306
|
lock = self.thread_lock()
|
|
254
307
|
lock_acquired = False
|
|
255
308
|
try:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if max_seconds == 0:
|
|
267
|
-
raise RuntimeError(f'Failed to access {self.cache_path}. '
|
|
268
|
-
f'Lock {sc_data_path_lock} still exists.')
|
|
269
|
-
time.sleep(1)
|
|
270
|
-
max_seconds -= 1
|
|
271
|
-
sc_data_path_lock.touch()
|
|
272
|
-
lock_acquired = True
|
|
273
|
-
if lock_acquired:
|
|
274
|
-
yield
|
|
309
|
+
timeout = self.timeout
|
|
310
|
+
while timeout > 0:
|
|
311
|
+
if lock.acquire_lock(timeout=1):
|
|
312
|
+
lock_acquired = True
|
|
313
|
+
break
|
|
314
|
+
sleep_time = random.randint(1, max(1, int(timeout / 10)))
|
|
315
|
+
timeout -= sleep_time + 1
|
|
316
|
+
time.sleep(sleep_time)
|
|
317
|
+
if lock_acquired:
|
|
318
|
+
yield
|
|
275
319
|
finally:
|
|
276
320
|
if lock.locked():
|
|
277
321
|
lock.release()
|
|
322
|
+
|
|
323
|
+
if not lock_acquired:
|
|
324
|
+
raise RuntimeError(f'Failed to access {self.cache_path}. '
|
|
325
|
+
f'Another thread is currently holding the lock.')
|
|
326
|
+
|
|
327
|
+
@contextlib.contextmanager
|
|
328
|
+
def __file_lock(self):
|
|
329
|
+
data_path_lock = InterProcessLock(self.lock_file)
|
|
330
|
+
lock_acquired = False
|
|
331
|
+
sc_data_path_lock = None
|
|
332
|
+
try:
|
|
333
|
+
try:
|
|
334
|
+
lock_acquired = data_path_lock.acquire(timeout=self.timeout)
|
|
335
|
+
except (OSError, RuntimeError):
|
|
336
|
+
if not lock_acquired:
|
|
337
|
+
sc_data_path_lock = Path(self.sc_lock_file)
|
|
338
|
+
max_seconds = self.timeout
|
|
339
|
+
while sc_data_path_lock.exists():
|
|
340
|
+
if max_seconds == 0:
|
|
341
|
+
raise RuntimeError(f'Failed to access {self.cache_path}. '
|
|
342
|
+
f'Lock {sc_data_path_lock} still exists.')
|
|
343
|
+
time.sleep(1)
|
|
344
|
+
max_seconds -= 1
|
|
345
|
+
sc_data_path_lock.touch()
|
|
346
|
+
lock_acquired = True
|
|
347
|
+
if lock_acquired:
|
|
348
|
+
yield
|
|
349
|
+
finally:
|
|
278
350
|
if lock_acquired:
|
|
279
351
|
if data_path_lock.acquired:
|
|
280
352
|
data_path_lock.release()
|
|
@@ -286,6 +358,12 @@ class RemoteResolver(Resolver):
|
|
|
286
358
|
f'{self.lock_file} is still locked, if this is a mistake, '
|
|
287
359
|
'please delete it.')
|
|
288
360
|
|
|
361
|
+
@contextlib.contextmanager
|
|
362
|
+
def lock(self):
|
|
363
|
+
with self.__thread_lock():
|
|
364
|
+
with self.__file_lock():
|
|
365
|
+
yield
|
|
366
|
+
|
|
289
367
|
def resolve_remote(self):
|
|
290
368
|
raise NotImplementedError("child class must implement this")
|
|
291
369
|
|
|
@@ -324,11 +402,8 @@ class FileResolver(Resolver):
|
|
|
324
402
|
|
|
325
403
|
@property
|
|
326
404
|
def urlpath(self):
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return parse.netloc
|
|
330
|
-
else:
|
|
331
|
-
return parse.path
|
|
405
|
+
# Rebuild URL and remove scheme prefix
|
|
406
|
+
return self.urlparse.geturl()[7:]
|
|
332
407
|
|
|
333
408
|
def resolve(self):
|
|
334
409
|
return os.path.abspath(self.urlpath)
|
|
@@ -412,6 +487,34 @@ class PythonPathResolver(Resolver):
|
|
|
412
487
|
path=path,
|
|
413
488
|
ref=ref)
|
|
414
489
|
|
|
490
|
+
@staticmethod
|
|
491
|
+
def set_dataroot(root,
|
|
492
|
+
package_name,
|
|
493
|
+
python_module,
|
|
494
|
+
alternative_path,
|
|
495
|
+
alternative_ref=None,
|
|
496
|
+
python_module_path_append=None):
|
|
497
|
+
'''
|
|
498
|
+
Helper function to register a python module as data source with an alternative in case
|
|
499
|
+
the module is not installed in an editable state
|
|
500
|
+
'''
|
|
501
|
+
# check if installed in an editable state
|
|
502
|
+
if PythonPathResolver.is_python_module_editable(python_module):
|
|
503
|
+
if python_module_path_append:
|
|
504
|
+
path = PythonPathResolver(
|
|
505
|
+
python_module, root, f"python://{python_module}").resolve()
|
|
506
|
+
path = os.path.abspath(os.path.join(path, python_module_path_append))
|
|
507
|
+
else:
|
|
508
|
+
path = f"python://{python_module}"
|
|
509
|
+
ref = None
|
|
510
|
+
else:
|
|
511
|
+
path = alternative_path
|
|
512
|
+
ref = alternative_ref
|
|
513
|
+
|
|
514
|
+
root.set_dataroot(name=package_name,
|
|
515
|
+
path=path,
|
|
516
|
+
tag=ref)
|
|
517
|
+
|
|
415
518
|
def resolve(self):
|
|
416
519
|
module = importlib.import_module(self.urlpath)
|
|
417
520
|
python_path = os.path.dirname(module.__file__)
|
|
@@ -53,17 +53,13 @@ class GithubResolver(HTTPResolver):
|
|
|
53
53
|
if not release:
|
|
54
54
|
release = repo.get_latest_release().tag_name
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
url = asset.url
|
|
56
|
+
repo_release = repo.get_release(release)
|
|
57
|
+
if repo_release:
|
|
58
|
+
for asset in repo_release.assets:
|
|
59
|
+
if asset.name == artifact:
|
|
60
|
+
return asset.url
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
raise ValueError(f'Unable to find release asset: {repository}/{release}/{artifact}')
|
|
65
|
-
|
|
66
|
-
return url
|
|
62
|
+
raise ValueError(f'Unable to find release asset: {repository}/{release}/{artifact}')
|
|
67
63
|
|
|
68
64
|
def __get_gh_auth(self):
|
|
69
65
|
token_name = self.name.upper()
|
siliconcompiler/packageschema.py
CHANGED
|
@@ -2,19 +2,270 @@ 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):
|
|
12
14
|
def __init__(self):
|
|
13
15
|
super().__init__()
|
|
14
16
|
|
|
15
17
|
schema_package(self)
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
def set_description(self, desc: str):
|
|
20
|
+
"""
|
|
21
|
+
Set the description of the package.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
desc (str): The description string.
|
|
25
|
+
"""
|
|
26
|
+
return self.set("package", "description", trim(desc))
|
|
27
|
+
|
|
28
|
+
def get_description(self) -> str:
|
|
29
|
+
"""Get the description of the package.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
str: The description string.
|
|
33
|
+
"""
|
|
34
|
+
return self.get("package", "description")
|
|
35
|
+
|
|
36
|
+
def set_version(self, version: str):
|
|
37
|
+
"""
|
|
38
|
+
Set the version of the package.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
version (str): The version string.
|
|
42
|
+
"""
|
|
43
|
+
return self.set("package", "version", version)
|
|
44
|
+
|
|
45
|
+
def get_version(self) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Get the version of the package.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
str: The version string.
|
|
51
|
+
"""
|
|
52
|
+
return self.get("package", "version")
|
|
53
|
+
|
|
54
|
+
def add_license(self, name: str):
|
|
55
|
+
"""
|
|
56
|
+
Add a license name to the package.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
name (str): The name of the license.
|
|
60
|
+
"""
|
|
61
|
+
return self.add("package", "license", name)
|
|
62
|
+
|
|
63
|
+
def add_licensefile(self, file: str, dataroot: str = None):
|
|
64
|
+
"""
|
|
65
|
+
Add a license file to the package.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
file (str): The path to the license file.
|
|
69
|
+
dataroot (str, optional): The data reference for the package. Defaults to None,
|
|
70
|
+
which uses the active package.
|
|
71
|
+
"""
|
|
72
|
+
if not dataroot:
|
|
73
|
+
dataroot = self._get_active("package")
|
|
74
|
+
with self.active_dataroot(dataroot):
|
|
75
|
+
return self.add("package", "licensefile", file)
|
|
76
|
+
|
|
77
|
+
def get_license(self) -> List[str]:
|
|
78
|
+
"""
|
|
79
|
+
Get a list of license names associated with the package.
|
|
80
|
+
"""
|
|
81
|
+
return self.get("package", "license")
|
|
82
|
+
|
|
83
|
+
def get_licensefile(self) -> List[str]:
|
|
84
|
+
"""
|
|
85
|
+
Get a list of license file paths associated with the package.
|
|
86
|
+
"""
|
|
87
|
+
return self.find_files("package", "licensefile")
|
|
88
|
+
|
|
89
|
+
def add_author(self,
|
|
90
|
+
identifier: str,
|
|
91
|
+
name: str = None,
|
|
92
|
+
email: str = None,
|
|
93
|
+
organization: str = None):
|
|
94
|
+
"""
|
|
95
|
+
Add or update author information for the package.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
identifier (str): A unique identifier for the author.
|
|
99
|
+
name (str, optional): The author's name. Defaults to None.
|
|
100
|
+
email (str, optional): The author's email address. Defaults to None.
|
|
101
|
+
organization (str, optional): The author's organization. Defaults to None.
|
|
102
|
+
"""
|
|
103
|
+
params = []
|
|
104
|
+
if name:
|
|
105
|
+
params.append(self.set("package", "author", identifier, "name", name))
|
|
106
|
+
if email:
|
|
107
|
+
params.append(self.set("package", "author", identifier, "email", email))
|
|
108
|
+
if organization:
|
|
109
|
+
params.append(self.set("package", "author", identifier, "organization", organization))
|
|
110
|
+
return [p for p in params if p]
|
|
111
|
+
|
|
112
|
+
def get_author(self, identifier: str = None):
|
|
113
|
+
"""
|
|
114
|
+
Returns the author information for a specific author or all authors.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
identifier (str): A unique identifier for the author, if None returns all
|
|
118
|
+
"""
|
|
119
|
+
if identifier is None:
|
|
120
|
+
authors = []
|
|
121
|
+
for author in self.getkeys("package", "author"):
|
|
122
|
+
authors.append(self.get_author(author))
|
|
123
|
+
return authors
|
|
124
|
+
return {
|
|
125
|
+
"name": self.get("package", "author", identifier, "name"),
|
|
126
|
+
"email": self.get("package", "author", identifier, "email"),
|
|
127
|
+
"organization": self.get("package", "author", identifier, "organization")
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
def add_doc(self, type: str, path: str, dataroot: str = None):
|
|
131
|
+
"""
|
|
132
|
+
Add documentation to the package.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
type (str): The type of documentation (e.g., "manual", "api").
|
|
136
|
+
path (str): The path to the documentation file.
|
|
137
|
+
dataroot (str, optional): The data reference for the package. Defaults to None,
|
|
138
|
+
which uses the active package.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
The result of the `add` operation.
|
|
142
|
+
"""
|
|
143
|
+
if not dataroot:
|
|
144
|
+
dataroot = self._get_active("package")
|
|
145
|
+
with self.active_dataroot(dataroot):
|
|
146
|
+
return self.add("package", "doc", type, path)
|
|
147
|
+
|
|
148
|
+
def get_doc(self, type: str = None) -> Union[List[str], Dict[str, List[str]]]:
|
|
149
|
+
"""
|
|
150
|
+
Get documentation files for the package.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
type (str, optional): The type of documentation to retrieve. If None,
|
|
154
|
+
returns all documentation organized by type. Defaults to None.
|
|
155
|
+
"""
|
|
156
|
+
if type:
|
|
157
|
+
return self.find_files("package", "doc", type)
|
|
158
|
+
|
|
159
|
+
docs = {}
|
|
160
|
+
for type in self.getkeys("package", "doc"):
|
|
161
|
+
doc_files = self.find_files("package", "doc", type)
|
|
162
|
+
if doc_files:
|
|
163
|
+
docs[type] = doc_files
|
|
164
|
+
return docs
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
############################################
|
|
168
|
+
# Package information
|
|
169
|
+
############################################
|
|
170
|
+
def schema_package(schema):
|
|
171
|
+
schema = EditableSchema(schema)
|
|
172
|
+
|
|
173
|
+
schema.insert(
|
|
174
|
+
'package', 'version',
|
|
175
|
+
Parameter(
|
|
176
|
+
'str',
|
|
177
|
+
scope=Scope.GLOBAL,
|
|
178
|
+
shorthelp="Package: version",
|
|
179
|
+
switch="-package_version <str>",
|
|
180
|
+
example=[
|
|
181
|
+
"cli: -package_version 1.0",
|
|
182
|
+
"api: chip.set('package', 'version', '1.0')"],
|
|
183
|
+
help=trim("""Package version. Can be a branch, tag, commit hash,
|
|
184
|
+
or a semver compatible version.""")))
|
|
185
|
+
|
|
186
|
+
schema.insert(
|
|
187
|
+
'package', 'description',
|
|
188
|
+
Parameter(
|
|
189
|
+
'str',
|
|
190
|
+
scope=Scope.GLOBAL,
|
|
191
|
+
shorthelp="Package: description",
|
|
192
|
+
switch="-package_description <str>",
|
|
193
|
+
example=[
|
|
194
|
+
"cli: -package_description 'Yet another cpu'",
|
|
195
|
+
"api: chip.set('package', 'description', 'Yet another cpu')"],
|
|
196
|
+
help=trim("""Package short one line description for package
|
|
197
|
+
managers and summary reports.""")))
|
|
198
|
+
|
|
199
|
+
for item in [
|
|
200
|
+
'datasheet',
|
|
201
|
+
'reference',
|
|
202
|
+
'userguide',
|
|
203
|
+
'quickstart',
|
|
204
|
+
'releasenotes',
|
|
205
|
+
'testplan',
|
|
206
|
+
'signoff',
|
|
207
|
+
'tutorial']:
|
|
208
|
+
schema.insert(
|
|
209
|
+
'package', 'doc', item,
|
|
210
|
+
Parameter(
|
|
211
|
+
'[file]',
|
|
212
|
+
scope=Scope.GLOBAL,
|
|
213
|
+
shorthelp=f"Package: {item} document",
|
|
214
|
+
switch=f"-package_doc_{item} <file>",
|
|
215
|
+
example=[
|
|
216
|
+
f"cli: -package_doc_{item} {item}.pdf",
|
|
217
|
+
f"api: chip.set('package', 'doc', '{item}', '{item}.pdf')"],
|
|
218
|
+
help=trim(f"""Package list of {item} documents.""")))
|
|
219
|
+
|
|
220
|
+
schema.insert(
|
|
221
|
+
'package', 'license',
|
|
222
|
+
Parameter(
|
|
223
|
+
'[str]',
|
|
224
|
+
scope=Scope.GLOBAL,
|
|
225
|
+
shorthelp="Package: license identifiers",
|
|
226
|
+
switch="-package_license <str>",
|
|
227
|
+
example=[
|
|
228
|
+
"cli: -package_license 'Apache-2.0'",
|
|
229
|
+
"api: chip.set('package', 'license', 'Apache-2.0')"],
|
|
230
|
+
help=trim("""Package list of SPDX license identifiers.""")))
|
|
231
|
+
|
|
232
|
+
schema.insert(
|
|
233
|
+
'package', 'licensefile',
|
|
234
|
+
Parameter(
|
|
235
|
+
'[file]',
|
|
236
|
+
scope=Scope.GLOBAL,
|
|
237
|
+
shorthelp="Package: license files",
|
|
238
|
+
switch="-package_licensefile <file>",
|
|
239
|
+
example=[
|
|
240
|
+
"cli: -package_licensefile './LICENSE'",
|
|
241
|
+
"api: chip.set('package', 'licensefile', './LICENSE')"],
|
|
242
|
+
help=trim("""Package list of license files for to be
|
|
243
|
+
applied in cases when a SPDX identifier is not available.
|
|
244
|
+
(eg. proprietary licenses).""")))
|
|
245
|
+
|
|
246
|
+
for item in [
|
|
247
|
+
'name',
|
|
248
|
+
'email',
|
|
249
|
+
'organization']:
|
|
250
|
+
schema.insert(
|
|
251
|
+
'package', 'author', 'default', item,
|
|
252
|
+
Parameter(
|
|
253
|
+
'str',
|
|
254
|
+
scope=Scope.GLOBAL,
|
|
255
|
+
shorthelp=f"Package: author {item}",
|
|
256
|
+
switch=f"-package_author_{item} 'userid <str>'",
|
|
257
|
+
example=[
|
|
258
|
+
f"cli: -package_author_{item} 'wiley wiley@acme.com'",
|
|
259
|
+
f"api: chip.set('package', 'author', 'wiley', '{item}', 'wiley@acme.com')"],
|
|
260
|
+
help=trim(f"""Package author {item} provided with full name as key and
|
|
261
|
+
{item} as value.""")))
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class PackageSchemaTmp(BaseSchema):
|
|
265
|
+
def __init__(self):
|
|
266
|
+
super().__init__()
|
|
267
|
+
|
|
268
|
+
schema_package_tmp(self)
|
|
18
269
|
|
|
19
270
|
def register(self, name, path, ref=None, clobber=True):
|
|
20
271
|
"""
|
|
@@ -60,7 +311,6 @@ class PackageSchema(BaseSchema):
|
|
|
60
311
|
resolver = resolver_cls(package, self._parent(root=True),
|
|
61
312
|
self.get("source", package, "path"),
|
|
62
313
|
self.get("source", package, "ref"))
|
|
63
|
-
resolver.set_cache(self.__cache)
|
|
64
314
|
return resolver
|
|
65
315
|
|
|
66
316
|
def get_resolvers(self):
|
|
@@ -73,17 +323,11 @@ class PackageSchema(BaseSchema):
|
|
|
73
323
|
|
|
74
324
|
return resolvers
|
|
75
325
|
|
|
76
|
-
def _set_cache(self, package, path):
|
|
77
|
-
self.__cache[package] = path
|
|
78
|
-
|
|
79
|
-
def get_path_cache(self):
|
|
80
|
-
return self.__cache.copy()
|
|
81
|
-
|
|
82
326
|
|
|
83
327
|
############################################
|
|
84
328
|
# Package information
|
|
85
329
|
############################################
|
|
86
|
-
def
|
|
330
|
+
def schema_package_tmp(schema):
|
|
87
331
|
schema = EditableSchema(schema)
|
|
88
332
|
|
|
89
333
|
schema.insert(
|