siliconcompiler 0.34.1__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/sc_show.py +1 -1
- 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 +3 -3
- siliconcompiler/dependencyschema.py +10 -174
- siliconcompiler/design.py +235 -118
- siliconcompiler/flowgraph.py +27 -14
- 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/package/__init__.py +138 -35
- siliconcompiler/package/github.py +6 -10
- siliconcompiler/packageschema.py +256 -12
- siliconcompiler/pathschema.py +226 -0
- siliconcompiler/project.py +459 -0
- siliconcompiler/scheduler/docker.py +2 -3
- siliconcompiler/scheduler/run_node.py +2 -1
- siliconcompiler/scheduler/scheduler.py +4 -13
- siliconcompiler/scheduler/schedulernode.py +25 -17
- siliconcompiler/scheduler/taskscheduler.py +2 -1
- siliconcompiler/schema/__init__.py +0 -2
- siliconcompiler/schema/baseschema.py +147 -24
- siliconcompiler/schema/editableschema.py +14 -6
- siliconcompiler/schema/journal.py +23 -15
- siliconcompiler/schema/namedschema.py +6 -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 +199 -10
- siliconcompiler/toolscripts/_tools.json +4 -4
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +3 -3
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +45 -35
- siliconcompiler/schema/packageschema.py +0 -101
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/top_level.txt +0 -0
siliconcompiler/design.py
CHANGED
|
@@ -3,19 +3,21 @@ import re
|
|
|
3
3
|
|
|
4
4
|
import os.path
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from typing import List
|
|
6
|
+
from typing import List, Union, Tuple, Dict
|
|
8
7
|
|
|
9
8
|
from siliconcompiler import utils
|
|
10
9
|
|
|
10
|
+
from siliconcompiler import PackageSchema
|
|
11
|
+
|
|
11
12
|
from siliconcompiler.dependencyschema import DependencySchema
|
|
13
|
+
from siliconcompiler.pathschema import PathSchema
|
|
12
14
|
from siliconcompiler.schema import NamedSchema
|
|
13
15
|
from siliconcompiler.schema import EditableSchema, Parameter, Scope
|
|
14
16
|
from siliconcompiler.schema.utils import trim
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
###########################################################################
|
|
18
|
-
class DesignSchema(NamedSchema, DependencySchema):
|
|
20
|
+
class DesignSchema(PackageSchema, NamedSchema, DependencySchema, PathSchema):
|
|
19
21
|
|
|
20
22
|
def __init__(self, name: str = None):
|
|
21
23
|
super().__init__()
|
|
@@ -23,7 +25,14 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
23
25
|
|
|
24
26
|
schema_design(self)
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
def add_dep(self, obj: NamedSchema, clobber: bool = True) -> bool:
|
|
29
|
+
if not isinstance(obj, NamedSchema):
|
|
30
|
+
raise TypeError(f"Cannot add an object of type: {type(obj)}")
|
|
31
|
+
|
|
32
|
+
if obj.name() == self.name():
|
|
33
|
+
raise ValueError("Cannot add a dependency with the same name")
|
|
34
|
+
|
|
35
|
+
return super().add_dep(obj, clobber=clobber)
|
|
27
36
|
|
|
28
37
|
############################################
|
|
29
38
|
def set_topmodule(self,
|
|
@@ -66,20 +75,20 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
66
75
|
value: str,
|
|
67
76
|
fileset: str = None,
|
|
68
77
|
clobber: bool = False,
|
|
69
|
-
|
|
78
|
+
dataroot: str = None) -> List[str]:
|
|
70
79
|
"""Adds include directories to a fileset.
|
|
71
80
|
|
|
72
81
|
Args:
|
|
73
82
|
value (str or Path): Include directory name.
|
|
74
83
|
fileset (str, optional): Fileset name.
|
|
75
84
|
clobber (bool, optional): Clears existing list before adding item
|
|
76
|
-
|
|
85
|
+
dataroot (str, optional): Data directory reference name
|
|
77
86
|
|
|
78
87
|
Returns:
|
|
79
88
|
list[str]: List of include directories
|
|
80
89
|
"""
|
|
81
90
|
return self.__set_add(fileset, 'idir', value, clobber, typelist=[str, list],
|
|
82
|
-
|
|
91
|
+
dataroot=dataroot)
|
|
83
92
|
|
|
84
93
|
def get_idir(self, fileset: str = None) -> List[str]:
|
|
85
94
|
"""Returns include directories for a fileset.
|
|
@@ -90,7 +99,7 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
90
99
|
Returns:
|
|
91
100
|
list[str]: List of include directories
|
|
92
101
|
"""
|
|
93
|
-
return self.__get(fileset, 'idir')
|
|
102
|
+
return self.__get(fileset, 'idir', is_file=True)
|
|
94
103
|
|
|
95
104
|
##############################################
|
|
96
105
|
def add_define(self,
|
|
@@ -155,20 +164,20 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
155
164
|
value: str,
|
|
156
165
|
fileset: str = None,
|
|
157
166
|
clobber: bool = False,
|
|
158
|
-
|
|
167
|
+
dataroot: str = None) -> List[str]:
|
|
159
168
|
"""Adds dynamic library directories to a fileset.
|
|
160
169
|
|
|
161
170
|
Args:
|
|
162
171
|
value (str or List[str]): Library directories
|
|
163
172
|
fileset (str, optional): Fileset name.
|
|
164
173
|
clobber (bool, optional): Clears existing list before adding item.
|
|
165
|
-
|
|
174
|
+
dataroot (str, optional): Data directory reference name
|
|
166
175
|
|
|
167
176
|
Returns:
|
|
168
177
|
list[str]: List of library directories.
|
|
169
178
|
"""
|
|
170
179
|
return self.__set_add(fileset, 'libdir', value, clobber, typelist=[str, list],
|
|
171
|
-
|
|
180
|
+
dataroot=dataroot)
|
|
172
181
|
|
|
173
182
|
def get_libdir(self, fileset: str = None) -> List[str]:
|
|
174
183
|
"""Returns dynamic library directories for a fileset.
|
|
@@ -179,7 +188,7 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
179
188
|
Returns:
|
|
180
189
|
list[str]: List of library directories.
|
|
181
190
|
"""
|
|
182
|
-
return self.__get(fileset, 'libdir')
|
|
191
|
+
return self.__get(fileset, 'libdir', is_file=True)
|
|
183
192
|
|
|
184
193
|
###############################################
|
|
185
194
|
def add_lib(self,
|
|
@@ -226,7 +235,7 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
226
235
|
"""
|
|
227
236
|
|
|
228
237
|
if fileset is None:
|
|
229
|
-
fileset = self.
|
|
238
|
+
fileset = self._get_active("fileset")
|
|
230
239
|
|
|
231
240
|
if not isinstance(fileset, str):
|
|
232
241
|
raise ValueError("fileset key must be a string")
|
|
@@ -249,19 +258,71 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
249
258
|
str: Parameter value
|
|
250
259
|
"""
|
|
251
260
|
if fileset is None:
|
|
252
|
-
fileset = self.
|
|
261
|
+
fileset = self._get_active("fileset")
|
|
253
262
|
|
|
254
263
|
if not isinstance(fileset, str):
|
|
255
|
-
raise ValueError("fileset
|
|
264
|
+
raise ValueError("fileset key must be a string")
|
|
256
265
|
return self.get('fileset', fileset, 'param', name)
|
|
257
266
|
|
|
267
|
+
###############################################
|
|
268
|
+
def add_depfileset(self, dep: Union["DesignSchema", str], depfileset: str, fileset: str = None):
|
|
269
|
+
"""
|
|
270
|
+
Record a reference to an imported dependency's fileset.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
dep (:class:`DesignSchema` or str): Dependency name or object.
|
|
274
|
+
depfileset (str): Dependency fileset
|
|
275
|
+
fileset (str): Fileset name.
|
|
276
|
+
|
|
277
|
+
"""
|
|
278
|
+
if fileset is None:
|
|
279
|
+
fileset = self._get_active("fileset")
|
|
280
|
+
|
|
281
|
+
if not isinstance(fileset, str):
|
|
282
|
+
raise ValueError("fileset key must be a string")
|
|
283
|
+
|
|
284
|
+
if isinstance(dep, str):
|
|
285
|
+
dep_name = dep
|
|
286
|
+
dep = self.get_dep(dep_name)
|
|
287
|
+
elif isinstance(dep, DesignSchema):
|
|
288
|
+
dep_name = dep.name()
|
|
289
|
+
self.add_dep(dep, clobber=True)
|
|
290
|
+
else:
|
|
291
|
+
raise TypeError("dep is not a valid type")
|
|
292
|
+
|
|
293
|
+
if not isinstance(dep, DesignSchema):
|
|
294
|
+
raise ValueError(f"cannot associate fileset ({depfileset}) with {dep.name()}")
|
|
295
|
+
|
|
296
|
+
if depfileset not in dep.getkeys("fileset"):
|
|
297
|
+
raise ValueError(f"{dep.name()} does not have {depfileset} as a fileset")
|
|
298
|
+
|
|
299
|
+
return self.add("fileset", fileset, "depfileset", (dep_name, depfileset))
|
|
300
|
+
|
|
301
|
+
def get_depfileset(self, fileset: str = None):
|
|
302
|
+
"""
|
|
303
|
+
Returns list of dependency filesets.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
fileset (str): Fileset name.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
list[str]: List of dependencies and filesets.
|
|
310
|
+
"""
|
|
311
|
+
if fileset is None:
|
|
312
|
+
fileset = self._get_active("fileset")
|
|
313
|
+
|
|
314
|
+
if not isinstance(fileset, str):
|
|
315
|
+
raise ValueError("fileset key must be a string")
|
|
316
|
+
|
|
317
|
+
return self.get("fileset", fileset, "depfileset")
|
|
318
|
+
|
|
258
319
|
###############################################
|
|
259
320
|
def add_file(self,
|
|
260
321
|
filename: str,
|
|
261
322
|
fileset: str = None,
|
|
262
323
|
filetype: str = None,
|
|
263
324
|
clobber: bool = False,
|
|
264
|
-
|
|
325
|
+
dataroot: str = None) -> List[str]:
|
|
265
326
|
"""
|
|
266
327
|
Adds files to a fileset.
|
|
267
328
|
|
|
@@ -277,7 +338,7 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
277
338
|
fileset (str): Logical group to associate the file with.
|
|
278
339
|
filetype (str, optional): Type of the file (e.g., 'verilog', 'sdc').
|
|
279
340
|
clobber (bool, optional): Clears list before adding item
|
|
280
|
-
|
|
341
|
+
dataroot (str, optional): Data directory reference name
|
|
281
342
|
|
|
282
343
|
Raises:
|
|
283
344
|
SiliconCompilerError: If fileset or filetype cannot be inferred from
|
|
@@ -294,17 +355,22 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
294
355
|
"""
|
|
295
356
|
|
|
296
357
|
if fileset is None:
|
|
297
|
-
fileset = self.
|
|
358
|
+
fileset = self._get_active("fileset")
|
|
359
|
+
|
|
360
|
+
if not isinstance(fileset, str):
|
|
361
|
+
raise ValueError("fileset key must be a string")
|
|
298
362
|
|
|
299
363
|
# handle list inputs
|
|
300
364
|
if isinstance(filename, (list, tuple)):
|
|
365
|
+
params = []
|
|
301
366
|
for item in filename:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
367
|
+
params.extend(
|
|
368
|
+
self.add_file(
|
|
369
|
+
item,
|
|
370
|
+
fileset=fileset,
|
|
371
|
+
clobber=clobber,
|
|
372
|
+
filetype=filetype))
|
|
373
|
+
return params
|
|
308
374
|
|
|
309
375
|
if filename is None:
|
|
310
376
|
raise ValueError("add_file cannot process None")
|
|
@@ -313,36 +379,24 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
313
379
|
filename = str(filename)
|
|
314
380
|
|
|
315
381
|
# map extension to default filetype/fileset
|
|
316
|
-
|
|
317
382
|
if not filetype:
|
|
318
383
|
ext = utils.get_file_ext(filename)
|
|
319
384
|
iomap = utils.get_default_iomap()
|
|
320
385
|
if ext in iomap:
|
|
321
|
-
|
|
386
|
+
_, default_filetype = iomap[ext]
|
|
322
387
|
filetype = default_filetype
|
|
323
388
|
else:
|
|
324
|
-
raise ValueError("
|
|
389
|
+
raise ValueError(f"Unrecognized file extension: {ext}")
|
|
325
390
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
raise ValueError(
|
|
329
|
-
f'Unable to infer fileset and/or filetype for '
|
|
330
|
-
f'{filename} based on file extension.')
|
|
391
|
+
if not dataroot:
|
|
392
|
+
dataroot = self._get_active("package")
|
|
331
393
|
|
|
332
394
|
# adding files to dictionary
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if package and params:
|
|
339
|
-
if not isinstance(params, (list, set, tuple)):
|
|
340
|
-
params = [params]
|
|
341
|
-
|
|
342
|
-
for param in params:
|
|
343
|
-
param.set(package, field="package")
|
|
344
|
-
|
|
345
|
-
return params
|
|
395
|
+
with self.active_dataroot(dataroot):
|
|
396
|
+
if clobber:
|
|
397
|
+
return self.set('fileset', fileset, 'file', filetype, filename)
|
|
398
|
+
else:
|
|
399
|
+
return self.add('fileset', fileset, 'file', filetype, filename)
|
|
346
400
|
|
|
347
401
|
###############################################
|
|
348
402
|
def get_file(self,
|
|
@@ -359,7 +413,7 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
359
413
|
"""
|
|
360
414
|
|
|
361
415
|
if fileset is None:
|
|
362
|
-
fileset = self.
|
|
416
|
+
fileset = self._get_active("fileset")
|
|
363
417
|
|
|
364
418
|
if not isinstance(fileset, list):
|
|
365
419
|
fileset = [fileset]
|
|
@@ -368,19 +422,22 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
368
422
|
filetype = [filetype]
|
|
369
423
|
|
|
370
424
|
filelist = []
|
|
371
|
-
for
|
|
372
|
-
if not isinstance(
|
|
425
|
+
for fs in fileset:
|
|
426
|
+
if not isinstance(fs, str):
|
|
373
427
|
raise ValueError("fileset key must be a string")
|
|
374
428
|
# handle scalar+list in argument
|
|
375
429
|
if not filetype:
|
|
376
|
-
filetype =
|
|
430
|
+
filetype = self.getkeys('fileset', fs, 'file')
|
|
377
431
|
# grab the files
|
|
378
|
-
for
|
|
379
|
-
filelist.extend(self.
|
|
432
|
+
for ftype in filetype:
|
|
433
|
+
filelist.extend(self.find_files('fileset', fs, 'file', ftype))
|
|
380
434
|
|
|
381
435
|
return filelist
|
|
382
436
|
|
|
383
|
-
def __write_flist(self,
|
|
437
|
+
def __write_flist(self,
|
|
438
|
+
filename: str,
|
|
439
|
+
filesets: List[str],
|
|
440
|
+
depalias: Dict[str, Tuple[NamedSchema, str]]):
|
|
384
441
|
written_cmd = set()
|
|
385
442
|
|
|
386
443
|
with open(filename, "w") as f:
|
|
@@ -394,33 +451,37 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
394
451
|
def write_header(header):
|
|
395
452
|
f.write(f"// {header}\n")
|
|
396
453
|
|
|
397
|
-
for lib in
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
454
|
+
for lib, fileset in self.get_fileset(filesets, depalias):
|
|
455
|
+
if lib.get('fileset', fileset, 'idir'):
|
|
456
|
+
write_header(f"{lib.name()} / {fileset} / include directories")
|
|
457
|
+
for idir in lib.find_files('fileset', fileset, 'idir'):
|
|
458
|
+
write(f"+incdir+{idir}")
|
|
459
|
+
|
|
460
|
+
if lib.get('fileset', fileset, 'define'):
|
|
461
|
+
write_header(f"{lib.name()} / {fileset} / defines")
|
|
462
|
+
for define in lib.get('fileset', fileset, 'define'):
|
|
463
|
+
write(f"+define+{define}")
|
|
402
464
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
465
|
+
for filetype in lib.getkeys('fileset', fileset, 'file'):
|
|
466
|
+
if lib.get('fileset', fileset, 'file', filetype):
|
|
467
|
+
write_header(f"{lib.name()} / {fileset} / {filetype} files")
|
|
468
|
+
for file in lib.find_files('fileset', fileset, 'file', filetype):
|
|
469
|
+
write(file)
|
|
407
470
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
for define in lib.get('fileset', fileset, 'define'):
|
|
411
|
-
write(f"+define+{define}")
|
|
471
|
+
def __map_fileformat(self, path):
|
|
472
|
+
_, ext = os.path.splitext(path)
|
|
412
473
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
write(file)
|
|
474
|
+
if ext == ".f":
|
|
475
|
+
return "flist"
|
|
476
|
+
else:
|
|
477
|
+
raise ValueError(f"Unable to determine filetype of: {path}")
|
|
418
478
|
|
|
419
479
|
###############################################
|
|
420
480
|
def write_fileset(self,
|
|
421
481
|
filename: str,
|
|
422
482
|
fileset: str = None,
|
|
423
|
-
fileformat: str = None
|
|
483
|
+
fileformat: str = None,
|
|
484
|
+
depalias: Dict[str, Tuple[NamedSchema, str]] = None) -> None:
|
|
424
485
|
"""Exports filesets to a standard formatted text file.
|
|
425
486
|
|
|
426
487
|
Currently supports Verilog `flist` format only.
|
|
@@ -431,13 +492,14 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
431
492
|
filename (str or Path): Output file name.
|
|
432
493
|
fileset (str or list[str]): Fileset(s) to export.
|
|
433
494
|
fileformat (str, optional): Export format.
|
|
495
|
+
depalias (dict of schema objects): Map of aliased objects
|
|
434
496
|
"""
|
|
435
497
|
|
|
436
498
|
if filename is None:
|
|
437
|
-
raise ValueError("
|
|
499
|
+
raise ValueError("filename cannot be None")
|
|
438
500
|
|
|
439
501
|
if fileset is None:
|
|
440
|
-
fileset = self.
|
|
502
|
+
fileset = self._get_active("fileset")
|
|
441
503
|
|
|
442
504
|
if not isinstance(fileset, list):
|
|
443
505
|
fileset = [fileset]
|
|
@@ -448,14 +510,12 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
448
510
|
|
|
449
511
|
# file extension lookup
|
|
450
512
|
if not fileformat:
|
|
451
|
-
|
|
452
|
-
formats['f'] = 'flist'
|
|
453
|
-
fileformat = formats[Path(filename).suffix.strip('.')]
|
|
513
|
+
fileformat = self.__map_fileformat(filename)
|
|
454
514
|
|
|
455
515
|
if fileformat == "flist":
|
|
456
|
-
self.__write_flist(filename, fileset)
|
|
516
|
+
self.__write_flist(filename, fileset, depalias)
|
|
457
517
|
else:
|
|
458
|
-
raise ValueError(f"{fileformat} is not supported")
|
|
518
|
+
raise ValueError(f"{fileformat} is not a supported filetype")
|
|
459
519
|
|
|
460
520
|
def __read_flist(self, filename: str, fileset: str):
|
|
461
521
|
# Extract information
|
|
@@ -485,26 +545,26 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
485
545
|
else:
|
|
486
546
|
files.append(expand_path(line))
|
|
487
547
|
|
|
488
|
-
# Create
|
|
548
|
+
# Create dataroots
|
|
489
549
|
all_paths = include_dirs + [os.path.dirname(f) for f in files]
|
|
490
550
|
all_paths = sorted(set(all_paths))
|
|
491
551
|
|
|
492
|
-
|
|
493
|
-
|
|
552
|
+
dataroot_root_name = f'flist-{self.name()}-{fileset}-{os.path.basename(filename)}'
|
|
553
|
+
dataroots = {}
|
|
494
554
|
|
|
495
555
|
for path_dir in all_paths:
|
|
496
556
|
found = False
|
|
497
|
-
for pdir in
|
|
557
|
+
for pdir in dataroots:
|
|
498
558
|
if path_dir.startswith(pdir):
|
|
499
559
|
found = True
|
|
500
560
|
break
|
|
501
561
|
if not found:
|
|
502
|
-
|
|
503
|
-
self.
|
|
504
|
-
|
|
562
|
+
dataroot_name = f"{dataroot_root_name}-{len(dataroots)}"
|
|
563
|
+
self.set_dataroot(dataroot_name, path_dir)
|
|
564
|
+
dataroots[path_dir] = dataroot_name
|
|
505
565
|
|
|
506
|
-
def
|
|
507
|
-
for pdir, name in
|
|
566
|
+
def get_dataroot(path):
|
|
567
|
+
for pdir, name in dataroots.items():
|
|
508
568
|
if path.startswith(pdir):
|
|
509
569
|
return name, pdir
|
|
510
570
|
return None, None
|
|
@@ -515,21 +575,21 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
515
575
|
self.add_define(defines)
|
|
516
576
|
if include_dirs:
|
|
517
577
|
for dir in include_dirs:
|
|
518
|
-
|
|
519
|
-
if
|
|
578
|
+
dataroot_name, pdir = get_dataroot(dir)
|
|
579
|
+
if dataroot_name:
|
|
520
580
|
dir = os.path.relpath(dir, pdir)
|
|
521
|
-
self.add_idir(dir,
|
|
581
|
+
self.add_idir(dir, dataroot=dataroot_name)
|
|
522
582
|
if files:
|
|
523
583
|
for f in files:
|
|
524
|
-
|
|
525
|
-
if
|
|
584
|
+
dataroot_name, pdir = get_dataroot(f)
|
|
585
|
+
if dataroot_name:
|
|
526
586
|
f = os.path.relpath(f, pdir)
|
|
527
|
-
self.add_file(f,
|
|
587
|
+
self.add_file(f, dataroot=dataroot_name)
|
|
528
588
|
|
|
529
589
|
################################################
|
|
530
590
|
def read_fileset(self,
|
|
531
591
|
filename: str,
|
|
532
|
-
fileset: str,
|
|
592
|
+
fileset: str = None,
|
|
533
593
|
fileformat=None) -> None:
|
|
534
594
|
"""Imports filesets from a standard formatted text file.
|
|
535
595
|
|
|
@@ -543,27 +603,28 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
543
603
|
"""
|
|
544
604
|
|
|
545
605
|
if filename is None:
|
|
546
|
-
raise ValueError("
|
|
606
|
+
raise ValueError("filename cannot be None")
|
|
547
607
|
|
|
548
608
|
if not fileformat:
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
609
|
+
fileformat = self.__map_fileformat(filename)
|
|
610
|
+
|
|
611
|
+
if fileset is None:
|
|
612
|
+
fileset = self._get_active("fileset")
|
|
552
613
|
|
|
553
614
|
if fileformat == "flist":
|
|
554
615
|
self.__read_flist(filename, fileset)
|
|
555
616
|
else:
|
|
556
|
-
raise ValueError(f"{fileformat} is not supported")
|
|
617
|
+
raise ValueError(f"{fileformat} is not a supported filetype")
|
|
557
618
|
|
|
558
619
|
################################################
|
|
559
620
|
# Helper Functions
|
|
560
621
|
################################################
|
|
561
|
-
def __set_add(self, fileset, option, value, clobber=False, typelist=None,
|
|
622
|
+
def __set_add(self, fileset, option, value, clobber=False, typelist=None, dataroot=None):
|
|
562
623
|
'''Sets a parameter value in schema.
|
|
563
624
|
'''
|
|
564
625
|
|
|
565
626
|
if fileset is None:
|
|
566
|
-
fileset = self.
|
|
627
|
+
fileset = self._get_active("fileset")
|
|
567
628
|
|
|
568
629
|
# check for a legal fileset
|
|
569
630
|
if not fileset or not isinstance(fileset, str):
|
|
@@ -581,28 +642,27 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
581
642
|
if value is None:
|
|
582
643
|
raise ValueError(f"None is an illegal {option} value")
|
|
583
644
|
|
|
584
|
-
if
|
|
585
|
-
|
|
586
|
-
else:
|
|
587
|
-
params = self.set('fileset', fileset, option, value)
|
|
588
|
-
|
|
589
|
-
if package and params:
|
|
590
|
-
if not isinstance(params, (list, set, tuple)):
|
|
591
|
-
params = [params]
|
|
645
|
+
if not dataroot:
|
|
646
|
+
dataroot = self._get_active("package")
|
|
592
647
|
|
|
593
|
-
|
|
594
|
-
|
|
648
|
+
with self.active_dataroot(dataroot):
|
|
649
|
+
if list in typelist and not clobber:
|
|
650
|
+
params = self.add('fileset', fileset, option, value)
|
|
651
|
+
else:
|
|
652
|
+
params = self.set('fileset', fileset, option, value)
|
|
595
653
|
|
|
596
654
|
return params
|
|
597
655
|
|
|
598
|
-
def __get(self, fileset, option):
|
|
656
|
+
def __get(self, fileset, option, is_file=False):
|
|
599
657
|
'''Gets a parameter value from schema.
|
|
600
658
|
'''
|
|
601
659
|
if fileset is None:
|
|
602
|
-
fileset = self.
|
|
660
|
+
fileset = self._get_active("fileset")
|
|
603
661
|
|
|
604
662
|
if not isinstance(fileset, str):
|
|
605
663
|
raise ValueError("fileset key must be a string")
|
|
664
|
+
if is_file:
|
|
665
|
+
return self.find_files('fileset', fileset, option)
|
|
606
666
|
return self.get('fileset', fileset, option)
|
|
607
667
|
|
|
608
668
|
@contextlib.contextmanager
|
|
@@ -627,9 +687,57 @@ class DesignSchema(NamedSchema, DependencySchema):
|
|
|
627
687
|
if not fileset:
|
|
628
688
|
raise ValueError("fileset cannot be an empty string")
|
|
629
689
|
|
|
630
|
-
self.
|
|
631
|
-
|
|
632
|
-
|
|
690
|
+
with self._active(fileset=fileset):
|
|
691
|
+
yield
|
|
692
|
+
|
|
693
|
+
def get_fileset(self,
|
|
694
|
+
filesets: Union[List[str], str],
|
|
695
|
+
alias: Dict[str, Tuple[NamedSchema, str]] = None) -> \
|
|
696
|
+
List[Tuple[NamedSchema, str]]:
|
|
697
|
+
"""
|
|
698
|
+
Computes the filesets this object required for a given set of filesets
|
|
699
|
+
|
|
700
|
+
Args:
|
|
701
|
+
filesets (list of str): List of filesets to evaluate
|
|
702
|
+
alias (dict of schema objects): Map of aliased objects
|
|
703
|
+
|
|
704
|
+
Returns:
|
|
705
|
+
List of tuples (dependency object, fileset)
|
|
706
|
+
"""
|
|
707
|
+
if alias is None:
|
|
708
|
+
alias = {}
|
|
709
|
+
|
|
710
|
+
if isinstance(filesets, str):
|
|
711
|
+
# Ensure we have a list
|
|
712
|
+
filesets = [filesets]
|
|
713
|
+
|
|
714
|
+
mapping = []
|
|
715
|
+
for fileset in filesets:
|
|
716
|
+
if not self.valid("fileset", fileset):
|
|
717
|
+
raise ValueError(f"{fileset} is not defined in {self.name()}")
|
|
718
|
+
|
|
719
|
+
mapping.append((self, fileset))
|
|
720
|
+
for dep, depfileset in self.get("fileset", fileset, "depfileset"):
|
|
721
|
+
if (dep, depfileset) in alias:
|
|
722
|
+
dep_obj, new_depfileset = alias[(dep, depfileset)]
|
|
723
|
+
if dep_obj is None:
|
|
724
|
+
continue
|
|
725
|
+
|
|
726
|
+
if new_depfileset:
|
|
727
|
+
depfileset = new_depfileset
|
|
728
|
+
else:
|
|
729
|
+
dep_obj = self.get_dep(dep)
|
|
730
|
+
if not isinstance(dep_obj, DesignSchema):
|
|
731
|
+
raise TypeError(f"{dep} must be a design object.")
|
|
732
|
+
|
|
733
|
+
mapping.extend(dep_obj.get_fileset(depfileset, alias))
|
|
734
|
+
|
|
735
|
+
# Cleanup
|
|
736
|
+
final_map = []
|
|
737
|
+
for cmap in mapping:
|
|
738
|
+
if cmap not in final_map:
|
|
739
|
+
final_map.append(cmap)
|
|
740
|
+
return final_map
|
|
633
741
|
|
|
634
742
|
|
|
635
743
|
###########################################################################
|
|
@@ -726,8 +834,7 @@ def schema_design(schema):
|
|
|
726
834
|
help=trim("""
|
|
727
835
|
Specifies directories to scan for libraries provided with the
|
|
728
836
|
:keypath:`lib` parameter. If multiple paths are provided, they are
|
|
729
|
-
searched based on the order of the libdir list.
|
|
730
|
-
parameter is translated to the '-y' option in verilog based tools.""")))
|
|
837
|
+
searched based on the order of the libdir list.""")))
|
|
731
838
|
|
|
732
839
|
schema.insert(
|
|
733
840
|
'fileset', fileset, 'lib',
|
|
@@ -756,3 +863,13 @@ def schema_design(schema):
|
|
|
756
863
|
data literals. The types of parameters and values supported is tightly
|
|
757
864
|
coupled to tools being used. For example, in Verilog only integer
|
|
758
865
|
literals (64'h4, 2'b0, 4) and strings are supported.""")))
|
|
866
|
+
|
|
867
|
+
schema.insert(
|
|
868
|
+
'fileset', fileset, 'depfileset',
|
|
869
|
+
Parameter(
|
|
870
|
+
'[(str,str)]',
|
|
871
|
+
scope=Scope.GLOBAL,
|
|
872
|
+
shorthelp="Design dependency fileset",
|
|
873
|
+
example=[
|
|
874
|
+
"api: chip.set('fileset', 'rtl, 'depfileset', ('lambdalib', 'rtl')"],
|
|
875
|
+
help=trim("""Sets the mapping for dependency filesets.""")))
|