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.
Files changed (114) hide show
  1. siliconcompiler/__init__.py +14 -2
  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 +1 -1
  6. siliconcompiler/apps/sc_remote.py +3 -3
  7. siliconcompiler/apps/sc_show.py +3 -3
  8. siliconcompiler/apps/utils/replay.py +4 -4
  9. siliconcompiler/checklist.py +203 -2
  10. siliconcompiler/constraints/__init__.py +17 -0
  11. siliconcompiler/constraints/asic_component.py +378 -0
  12. siliconcompiler/constraints/asic_floorplan.py +449 -0
  13. siliconcompiler/constraints/asic_pins.py +489 -0
  14. siliconcompiler/constraints/asic_timing.py +517 -0
  15. siliconcompiler/core.py +31 -249
  16. siliconcompiler/data/templates/email/general.j2 +3 -3
  17. siliconcompiler/data/templates/email/summary.j2 +1 -1
  18. siliconcompiler/data/templates/issue/README.txt +1 -1
  19. siliconcompiler/data/templates/report/sc_report.j2 +7 -7
  20. siliconcompiler/dependencyschema.py +10 -174
  21. siliconcompiler/design.py +325 -114
  22. siliconcompiler/flowgraph.py +63 -15
  23. siliconcompiler/library.py +133 -0
  24. siliconcompiler/metric.py +94 -72
  25. siliconcompiler/metrics/__init__.py +7 -0
  26. siliconcompiler/metrics/asic.py +245 -0
  27. siliconcompiler/metrics/fpga.py +220 -0
  28. siliconcompiler/optimizer/vizier.py +2 -2
  29. siliconcompiler/package/__init__.py +138 -35
  30. siliconcompiler/package/github.py +6 -10
  31. siliconcompiler/packageschema.py +256 -12
  32. siliconcompiler/pathschema.py +226 -0
  33. siliconcompiler/pdk.py +5 -5
  34. siliconcompiler/project.py +459 -0
  35. siliconcompiler/remote/client.py +18 -12
  36. siliconcompiler/remote/server.py +2 -2
  37. siliconcompiler/report/dashboard/cli/__init__.py +6 -6
  38. siliconcompiler/report/dashboard/cli/board.py +3 -3
  39. siliconcompiler/report/dashboard/web/components/__init__.py +5 -5
  40. siliconcompiler/report/dashboard/web/components/flowgraph.py +4 -4
  41. siliconcompiler/report/dashboard/web/components/graph.py +2 -2
  42. siliconcompiler/report/dashboard/web/state.py +1 -1
  43. siliconcompiler/report/dashboard/web/utils/__init__.py +5 -5
  44. siliconcompiler/report/html_report.py +1 -1
  45. siliconcompiler/report/report.py +4 -4
  46. siliconcompiler/report/summary_table.py +2 -2
  47. siliconcompiler/report/utils.py +5 -5
  48. siliconcompiler/scheduler/docker.py +4 -10
  49. siliconcompiler/scheduler/run_node.py +4 -8
  50. siliconcompiler/scheduler/scheduler.py +18 -24
  51. siliconcompiler/scheduler/schedulernode.py +161 -143
  52. siliconcompiler/scheduler/send_messages.py +3 -3
  53. siliconcompiler/scheduler/slurm.py +5 -3
  54. siliconcompiler/scheduler/taskscheduler.py +10 -8
  55. siliconcompiler/schema/__init__.py +0 -2
  56. siliconcompiler/schema/baseschema.py +148 -26
  57. siliconcompiler/schema/editableschema.py +14 -6
  58. siliconcompiler/schema/journal.py +23 -15
  59. siliconcompiler/schema/namedschema.py +30 -4
  60. siliconcompiler/schema/parameter.py +34 -19
  61. siliconcompiler/schema/parametertype.py +2 -0
  62. siliconcompiler/schema/parametervalue.py +198 -15
  63. siliconcompiler/schema/schema_cfg.py +18 -14
  64. siliconcompiler/schema_obj.py +5 -3
  65. siliconcompiler/tool.py +591 -179
  66. siliconcompiler/tools/__init__.py +2 -0
  67. siliconcompiler/tools/builtin/_common.py +5 -5
  68. siliconcompiler/tools/builtin/concatenate.py +5 -5
  69. siliconcompiler/tools/builtin/minimum.py +4 -4
  70. siliconcompiler/tools/builtin/mux.py +4 -4
  71. siliconcompiler/tools/builtin/nop.py +4 -4
  72. siliconcompiler/tools/builtin/verify.py +7 -7
  73. siliconcompiler/tools/execute/exec_input.py +1 -1
  74. siliconcompiler/tools/genfasm/genfasm.py +1 -6
  75. siliconcompiler/tools/openroad/_apr.py +5 -1
  76. siliconcompiler/tools/openroad/antenna_repair.py +1 -1
  77. siliconcompiler/tools/openroad/macro_placement.py +1 -1
  78. siliconcompiler/tools/openroad/power_grid.py +1 -1
  79. siliconcompiler/tools/openroad/scripts/common/procs.tcl +5 -0
  80. siliconcompiler/tools/opensta/timing.py +26 -3
  81. siliconcompiler/tools/slang/__init__.py +2 -2
  82. siliconcompiler/tools/surfer/__init__.py +0 -0
  83. siliconcompiler/tools/surfer/show.py +53 -0
  84. siliconcompiler/tools/surfer/surfer.py +30 -0
  85. siliconcompiler/tools/vpr/route.py +27 -14
  86. siliconcompiler/tools/vpr/vpr.py +23 -6
  87. siliconcompiler/tools/yosys/__init__.py +1 -1
  88. siliconcompiler/tools/yosys/scripts/procs.tcl +143 -0
  89. siliconcompiler/tools/yosys/{sc_synth_asic.tcl → scripts/sc_synth_asic.tcl} +4 -0
  90. siliconcompiler/tools/yosys/{sc_synth_fpga.tcl → scripts/sc_synth_fpga.tcl} +24 -77
  91. siliconcompiler/tools/yosys/syn_fpga.py +14 -0
  92. siliconcompiler/toolscripts/_tools.json +9 -13
  93. siliconcompiler/toolscripts/rhel9/install-vpr.sh +0 -2
  94. siliconcompiler/toolscripts/ubuntu22/install-surfer.sh +33 -0
  95. siliconcompiler/toolscripts/ubuntu24/install-surfer.sh +33 -0
  96. siliconcompiler/utils/__init__.py +2 -1
  97. siliconcompiler/utils/flowgraph.py +24 -23
  98. siliconcompiler/utils/issue.py +23 -29
  99. siliconcompiler/utils/logging.py +35 -6
  100. siliconcompiler/utils/showtools.py +6 -1
  101. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +15 -25
  102. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +109 -97
  103. siliconcompiler/schema/packageschema.py +0 -101
  104. siliconcompiler/tools/yosys/procs.tcl +0 -71
  105. siliconcompiler/toolscripts/rhel9/install-yosys-parmys.sh +0 -68
  106. siliconcompiler/toolscripts/ubuntu22/install-yosys-parmys.sh +0 -68
  107. siliconcompiler/toolscripts/ubuntu24/install-yosys-parmys.sh +0 -68
  108. /siliconcompiler/tools/yosys/{sc_lec.tcl → scripts/sc_lec.tcl} +0 -0
  109. /siliconcompiler/tools/yosys/{sc_screenshot.tcl → scripts/sc_screenshot.tcl} +0 -0
  110. /siliconcompiler/tools/yosys/{syn_strategies.tcl → scripts/syn_strategies.tcl} +0 -0
  111. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
  112. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
  113. {siliconcompiler-0.34.0.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
  114. {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.__cache = {}
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
- if self.name in self.__cache:
145
- return self.__cache[self.name]
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 and self.name not in self.__cache:
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
- self.__cache[self.name] = path
156
- return self.__cache[self.name]
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 lock(self):
305
+ def __thread_lock(self):
253
306
  lock = self.thread_lock()
254
307
  lock_acquired = False
255
308
  try:
256
- if lock.acquire_lock(timeout=self.timeout):
257
- data_path_lock = InterProcessLock(self.lock_file)
258
- sc_data_path_lock = None
259
- try:
260
- lock_acquired = data_path_lock.acquire(timeout=self.timeout)
261
- except (OSError, RuntimeError):
262
- if not lock_acquired:
263
- sc_data_path_lock = Path(self.sc_lock_file)
264
- max_seconds = self.timeout
265
- while sc_data_path_lock.exists():
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
- parse = self.urlparse
328
- if parse.netloc:
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
- url = None
57
- for repo_release in repo.get_releases():
58
- if repo_release.tag_name == release:
59
- for asset in repo_release.assets:
60
- if asset.name == artifact:
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
- if not url:
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()
@@ -2,19 +2,270 @@ import os
2
2
 
3
3
  import os.path
4
4
 
5
- from siliconcompiler.schema import BaseSchema
6
- from siliconcompiler.schema import EditableSchema, Parameter, Scope
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(BaseSchema):
13
+ class PackageSchema(PathSchema):
12
14
  def __init__(self):
13
15
  super().__init__()
14
16
 
15
17
  schema_package(self)
16
18
 
17
- self.__cache = {}
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 schema_package(schema):
330
+ def schema_package_tmp(schema):
87
331
  schema = EditableSchema(schema)
88
332
 
89
333
  schema.insert(