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.
Files changed (46) hide show
  1. siliconcompiler/__init__.py +14 -2
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc_show.py +1 -1
  4. siliconcompiler/constraints/__init__.py +17 -0
  5. siliconcompiler/constraints/asic_component.py +378 -0
  6. siliconcompiler/constraints/asic_floorplan.py +449 -0
  7. siliconcompiler/constraints/asic_pins.py +489 -0
  8. siliconcompiler/constraints/asic_timing.py +517 -0
  9. siliconcompiler/core.py +3 -3
  10. siliconcompiler/dependencyschema.py +10 -174
  11. siliconcompiler/design.py +235 -118
  12. siliconcompiler/flowgraph.py +27 -14
  13. siliconcompiler/library.py +133 -0
  14. siliconcompiler/metric.py +94 -72
  15. siliconcompiler/metrics/__init__.py +7 -0
  16. siliconcompiler/metrics/asic.py +245 -0
  17. siliconcompiler/metrics/fpga.py +220 -0
  18. siliconcompiler/package/__init__.py +138 -35
  19. siliconcompiler/package/github.py +6 -10
  20. siliconcompiler/packageschema.py +256 -12
  21. siliconcompiler/pathschema.py +226 -0
  22. siliconcompiler/project.py +459 -0
  23. siliconcompiler/scheduler/docker.py +2 -3
  24. siliconcompiler/scheduler/run_node.py +2 -1
  25. siliconcompiler/scheduler/scheduler.py +4 -13
  26. siliconcompiler/scheduler/schedulernode.py +25 -17
  27. siliconcompiler/scheduler/taskscheduler.py +2 -1
  28. siliconcompiler/schema/__init__.py +0 -2
  29. siliconcompiler/schema/baseschema.py +147 -24
  30. siliconcompiler/schema/editableschema.py +14 -6
  31. siliconcompiler/schema/journal.py +23 -15
  32. siliconcompiler/schema/namedschema.py +6 -4
  33. siliconcompiler/schema/parameter.py +34 -19
  34. siliconcompiler/schema/parametertype.py +2 -0
  35. siliconcompiler/schema/parametervalue.py +198 -15
  36. siliconcompiler/schema/schema_cfg.py +18 -14
  37. siliconcompiler/schema_obj.py +5 -3
  38. siliconcompiler/tool.py +199 -10
  39. siliconcompiler/toolscripts/_tools.json +4 -4
  40. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +3 -3
  41. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +45 -35
  42. siliconcompiler/schema/packageschema.py +0 -101
  43. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
  44. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
  45. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
  46. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/top_level.txt +0 -0
@@ -11,7 +11,8 @@ import shlex
11
11
 
12
12
  from enum import Enum
13
13
 
14
- from .parametervalue import NodeValue, DirectoryNodeValue, FileNodeValue, NodeListValue
14
+ from .parametervalue import NodeValue, DirectoryNodeValue, FileNodeValue, NodeListValue, \
15
+ NodeSetValue
15
16
  from .parametertype import NodeType, NodeEnumType
16
17
 
17
18
 
@@ -59,6 +60,7 @@ class Parameter:
59
60
  example (list of str): example field
60
61
  help (str): help field
61
62
  pernode (:class:`.PerNode`): pernode field
63
+ kwargs: forwarded to default value constructor
62
64
  '''
63
65
 
64
66
  GLOBAL_KEY = 'global'
@@ -77,7 +79,8 @@ class Parameter:
77
79
  switch=None,
78
80
  example=None,
79
81
  help=None,
80
- pernode=PerNode.NEVER):
82
+ pernode=PerNode.NEVER,
83
+ **kwargs):
81
84
 
82
85
  self.__type = NodeType.parse(type)
83
86
  self.__scope = Scope(scope)
@@ -108,7 +111,7 @@ class Parameter:
108
111
 
109
112
  self.__pernode = PerNode(pernode)
110
113
 
111
- self.__setdefvalue(defvalue)
114
+ self.__setdefvalue(defvalue, **kwargs)
112
115
 
113
116
  self.__node = {}
114
117
 
@@ -123,26 +126,33 @@ class Parameter:
123
126
  self.__hashalgo = str(hashalgo)
124
127
  self.__copy = bool(copy)
125
128
 
126
- def __setdefvalue(self, defvalue):
129
+ def __setdefvalue(self, defvalue, **kwargs):
127
130
  if NodeType.contains(self.__type, 'file'):
128
- base = FileNodeValue(defvalue)
129
131
  if isinstance(self.__type, list):
130
- self.__defvalue = NodeListValue(base)
132
+ self.__defvalue = NodeListValue(FileNodeValue(defvalue, **kwargs))
133
+ elif isinstance(self.__type, set):
134
+ self.__defvalue = NodeSetValue(FileNodeValue(defvalue, **kwargs))
131
135
  else:
132
- self.__defvalue = base
136
+ self.__defvalue = FileNodeValue(defvalue, **kwargs)
133
137
  elif NodeType.contains(self.__type, 'dir'):
134
- base = DirectoryNodeValue(defvalue)
135
138
  if isinstance(self.__type, list):
136
- self.__defvalue = NodeListValue(base)
139
+ self.__defvalue = NodeListValue(DirectoryNodeValue(defvalue, **kwargs))
140
+ elif isinstance(self.__type, set):
141
+ self.__defvalue = NodeSetValue(DirectoryNodeValue(defvalue, **kwargs))
137
142
  else:
138
- self.__defvalue = base
143
+ self.__defvalue = DirectoryNodeValue(defvalue, **kwargs)
139
144
  else:
145
+ kwargs = {}
140
146
  if isinstance(self.__type, list):
141
- self.__defvalue = NodeListValue(NodeValue(self.__type[0]))
147
+ self.__defvalue = NodeListValue(NodeValue(self.__type[0], **kwargs))
148
+ if defvalue:
149
+ self.__defvalue.set(defvalue)
150
+ elif isinstance(self.__type, set):
151
+ self.__defvalue = NodeSetValue(NodeValue(list(self.__type)[0], **kwargs))
142
152
  if defvalue:
143
153
  self.__defvalue.set(defvalue)
144
154
  else:
145
- self.__defvalue = NodeValue(self.__type, value=defvalue)
155
+ self.__defvalue = NodeValue(self.__type, value=defvalue, **kwargs)
146
156
 
147
157
  def __str__(self):
148
158
  return str(self.getvalues())
@@ -344,7 +354,7 @@ class Parameter:
344
354
 
345
355
  if field in self.__defvalue.fields:
346
356
  if not self.is_list() and field == 'value':
347
- raise ValueError("add can only be used on lists")
357
+ raise ValueError("add can only be used on lists or sets")
348
358
 
349
359
  if isinstance(index, int):
350
360
  index = str(index)
@@ -409,6 +419,12 @@ class Parameter:
409
419
 
410
420
  return True
411
421
 
422
+ def reset(self):
423
+ """
424
+ Resets a parameter back to its default state
425
+ """
426
+ self.__node = {}
427
+
412
428
  def getdict(self, include_default=True, values_only=False):
413
429
  """
414
430
  Returns a schema dictionary.
@@ -523,15 +539,14 @@ class Parameter:
523
539
  requires_set = NodeType.contains(self.__type, tuple) or NodeType.contains(self.__type, set)
524
540
 
525
541
  try:
526
- defvalue = manifest["node"]["default"]["default"]["value"]
542
+ defvalue = manifest["node"]["default"]["default"]
527
543
  del manifest["node"]["default"]
528
544
  except KeyError:
529
545
  defvalue = None
530
546
 
531
- if requires_set:
532
- self.__setdefvalue(NodeType.normalize(defvalue, self.__type))
533
- else:
534
- self.__setdefvalue(defvalue)
547
+ self.__setdefvalue(None)
548
+ if defvalue:
549
+ self.__defvalue._from_dict(defvalue, keypath, version)
535
550
 
536
551
  for step, indexdata in manifest["node"].items():
537
552
  self.__node[step] = {}
@@ -607,7 +622,7 @@ class Parameter:
607
622
  Returns true is this parameter is a list type
608
623
  """
609
624
 
610
- return isinstance(self.__type, list)
625
+ return isinstance(self.__type, (list, set))
611
626
 
612
627
  def is_empty(self):
613
628
  '''
@@ -100,6 +100,8 @@ class NodeType:
100
100
  return True
101
101
  if isinstance(value, list):
102
102
  return NodeType.contains(value[0], check)
103
+ if isinstance(value, set):
104
+ return NodeType.contains(list(value)[0], check)
103
105
  if isinstance(value, tuple):
104
106
  return any([NodeType.contains(v, check) for v in value])
105
107
  return value == check
@@ -83,11 +83,15 @@ class NodeListValue:
83
83
  field (str): name of schema field.
84
84
  """
85
85
 
86
- vals = []
87
- for val in self.__values:
88
- value = val.get(field=field)
89
- vals.append(value)
90
- return vals
86
+ if self.__values:
87
+ vals = []
88
+ for val in self.__values:
89
+ vals.append(val.get(field=field))
90
+ return vals
91
+ if self.__base.get("value") is None:
92
+ return []
93
+
94
+ return [self.__base.get(field=field)]
91
95
 
92
96
  def set(self, value, field='value'):
93
97
  """
@@ -178,6 +182,185 @@ class NodeListValue:
178
182
  return [self.__base.type]
179
183
 
180
184
 
185
+ class NodeSetValue:
186
+ '''
187
+ Holds the data for a set schema type.
188
+
189
+ Args:
190
+ base (:class:`NodeValue`): base type for this set.
191
+ '''
192
+
193
+ def __init__(self, base):
194
+ self.__base = base
195
+ self.__values = []
196
+
197
+ def getdict(self):
198
+ """
199
+ Returns a schema dictionary.
200
+
201
+ Examples:
202
+ >>> value.getdict()
203
+ Returns the complete dictionary for the value
204
+ """
205
+
206
+ manifest = {}
207
+ for field in self.fields:
208
+ if field is None:
209
+ continue
210
+
211
+ value = self.get(field=field, ordered=True)
212
+ manifest.setdefault(field, []).extend(value)
213
+
214
+ if field == "author":
215
+ tmplist = []
216
+ for a in manifest[field]:
217
+ tmplist.extend(a)
218
+ manifest[field] = tmplist
219
+ return manifest
220
+
221
+ def _from_dict(self, manifest, keypath, version):
222
+ '''
223
+ Create a new value based on the provided dictionary.
224
+
225
+ Args:
226
+ manifest (dict): Manifest to decide.
227
+ keypath (list of str): Path to the current keypath.
228
+ version (packaging.Version): Version of the dictionary schema
229
+ sctype (str): schema type for this value
230
+ '''
231
+
232
+ self.__values.clear()
233
+ for n in range(len(manifest["value"])):
234
+ param = self.__base.copy()
235
+ self.__values.append(param)
236
+
237
+ for field in self.fields:
238
+ if field is None:
239
+ continue
240
+
241
+ if len(manifest[field]) <= n:
242
+ continue
243
+ param.set(manifest[field][n], field=field)
244
+
245
+ def get(self, field='value', ordered: bool = False):
246
+ """
247
+ Returns the value in the specified field
248
+
249
+ Args:
250
+ field (str): name of schema field.
251
+ ordered (bool): if true, returns a list instead of set for values
252
+ """
253
+
254
+ vals = []
255
+
256
+ if self.__values:
257
+ for val in self.__values:
258
+ vals.append(val.get(field=field))
259
+ elif self.__base.get("value") is None:
260
+ pass
261
+ else:
262
+ vals.append(self.__base.get(field=field))
263
+
264
+ if not ordered and field == "value":
265
+ return set(vals)
266
+ return vals
267
+
268
+ def set(self, value, field='value'):
269
+ value = NodeType.normalize(value, [self.__base.type])
270
+
271
+ if field == 'value':
272
+ self.__values.clear()
273
+ else:
274
+ if len(value) != len(self.__values):
275
+ raise ValueError(f"set on {field} field must match number of values")
276
+
277
+ current_values = []
278
+ if field == "value":
279
+ current_values = [v.get() for v in self.__values]
280
+
281
+ modified = list()
282
+ m = 0
283
+ for n in range(len(value)):
284
+ if field == 'value':
285
+ if value[n] in current_values:
286
+ continue
287
+
288
+ self.__values.append(self.__base.copy())
289
+ current_values.append(value[n])
290
+ self.__values[m].set(value[n], field=field)
291
+ modified.append(self.__values[m])
292
+ m += 1
293
+ return tuple(modified)
294
+
295
+ def add(self, value, field='value'):
296
+ """
297
+ Adds the value in a specific field and ensures it has been normalized.
298
+
299
+ Returns:
300
+ tuple of modified values
301
+
302
+ Args:
303
+ value (any): value to set
304
+ field (str): field to set
305
+ """
306
+
307
+ current_values = []
308
+ if field == "value":
309
+ current_values = [v.get() for v in self.__values]
310
+
311
+ modified = list()
312
+ if field == 'value':
313
+ value = NodeType.normalize(value, [self.__base.type])
314
+
315
+ for n in range(len(value)):
316
+ if value[n] in current_values:
317
+ continue
318
+
319
+ self.__values.append(self.__base.copy())
320
+ self.__values[-1].set(value[n], field=field)
321
+ current_values.append(value[n])
322
+ modified.append(self.__values[-1])
323
+ else:
324
+ for val in self.__values:
325
+ val.add(value, field=field)
326
+ modified.append(val)
327
+ return tuple(modified)
328
+
329
+ @property
330
+ def fields(self):
331
+ """
332
+ Returns a list of valid fields for this value
333
+ """
334
+ return self.__base.fields
335
+
336
+ @property
337
+ def values(self):
338
+ '''
339
+ Returns a copy of the values stored in the list
340
+ '''
341
+ return self.__values.copy()
342
+
343
+ def copy(self):
344
+ """
345
+ Returns a copy of this value.
346
+ """
347
+
348
+ return copy.deepcopy(self)
349
+
350
+ def _set_type(self, sctype):
351
+ sctype = NodeType.parse(sctype)[0]
352
+ self.__base._set_type(sctype)
353
+ for val in self.__values:
354
+ val._set_type(sctype)
355
+
356
+ @property
357
+ def type(self):
358
+ """
359
+ Returns the type for this value
360
+ """
361
+ return set([self.__base.type])
362
+
363
+
181
364
  class NodeValue:
182
365
  '''
183
366
  Holds the data for a parameter.
@@ -375,10 +558,10 @@ class PathNodeValue(NodeValue):
375
558
  value (any): default value for this parameter
376
559
  '''
377
560
 
378
- def __init__(self, type, value=None):
561
+ def __init__(self, type, value=None, package=None):
379
562
  super().__init__(type, value=value)
380
563
  self.__filehash = None
381
- self.__package = None
564
+ self.__package = package
382
565
 
383
566
  def getdict(self):
384
567
  return {
@@ -439,7 +622,7 @@ class PathNodeValue(NodeValue):
439
622
 
440
623
  return None
441
624
 
442
- def resolve_path(self, search=None, collection_dir=None):
625
+ def resolve_path(self, search=None, collection_dir=None) -> str:
443
626
  """
444
627
  Resolve the path of this value.
445
628
 
@@ -457,10 +640,10 @@ class PathNodeValue(NodeValue):
457
640
  if collection_dir:
458
641
  collect_path = self.__resolve_collection_path(value, collection_dir)
459
642
  if collect_path:
460
- return collect_path
643
+ return str(pathlib.Path(collect_path))
461
644
 
462
645
  if os.path.isabs(value) and os.path.exists(value):
463
- return value
646
+ return str(pathlib.Path(value))
464
647
 
465
648
  # Search for file
466
649
  if search is None:
@@ -469,7 +652,7 @@ class PathNodeValue(NodeValue):
469
652
  for searchdir in search:
470
653
  abspath = os.path.abspath(os.path.join(searchdir, value))
471
654
  if os.path.exists(abspath):
472
- return abspath
655
+ return str(pathlib.Path(abspath))
473
656
 
474
657
  # File not found
475
658
  raise FileNotFoundError(value)
@@ -603,8 +786,8 @@ class DirectoryNodeValue(PathNodeValue):
603
786
  value (any): default value for this parameter
604
787
  '''
605
788
 
606
- def __init__(self, value=None):
607
- super().__init__("dir", value=value)
789
+ def __init__(self, value=None, package=None):
790
+ super().__init__("dir", value=value, package=package)
608
791
 
609
792
  def hash(self, function, **kwargs):
610
793
  """
@@ -631,8 +814,8 @@ class FileNodeValue(PathNodeValue):
631
814
  value (any): default value for this parameter
632
815
  '''
633
816
 
634
- def __init__(self, value=None):
635
- super().__init__("file", value=value)
817
+ def __init__(self, value=None, package=None):
818
+ super().__init__("file", value=value, package=package)
636
819
  self.__date = None
637
820
  self.__author = []
638
821
 
@@ -59,16 +59,7 @@ def schema_cfg(schema):
59
59
  # Basic schema setup
60
60
  cfg = EditableSchema(schema)
61
61
 
62
- scparam(cfg, ['schemaversion'],
63
- sctype='str',
64
- scope=Scope.GLOBAL,
65
- defvalue=SCHEMA_VERSION,
66
- require=True,
67
- shorthelp="Schema version number",
68
- lock=True,
69
- switch="-schemaversion <str>",
70
- example=["api: chip.get('schemaversion')"],
71
- schelp="""SiliconCompiler schema version number.""")
62
+ schema_version(cfg)
72
63
 
73
64
  # Design topmodule/entrypoint
74
65
  scparam(cfg, ['design'],
@@ -139,6 +130,19 @@ def schema_cfg(schema):
139
130
  cfg = schema_schematic(cfg)
140
131
 
141
132
 
133
+ def schema_version(cfg):
134
+ scparam(cfg, ['schemaversion'],
135
+ sctype='str',
136
+ scope=Scope.GLOBAL,
137
+ defvalue=SCHEMA_VERSION,
138
+ require=True,
139
+ shorthelp="Schema version number",
140
+ lock=True,
141
+ switch="-schemaversion <str>",
142
+ example=["api: chip.get('schemaversion')"],
143
+ schelp="""SiliconCompiler schema version number.""")
144
+
145
+
142
146
  ###############################################################################
143
147
  # SCHEMATIC
144
148
  ###############################################################################
@@ -1071,8 +1075,8 @@ def schema_arg(cfg):
1071
1075
  # Metrics to Track
1072
1076
  ###########################################################################
1073
1077
  def schema_metric(cfg):
1074
- from siliconcompiler.metric import MetricSchema
1075
- cfg.insert("metric", MetricSchema())
1078
+ from siliconcompiler.metric import MetricSchemaTmp
1079
+ cfg.insert("metric", MetricSchemaTmp())
1076
1080
  return cfg
1077
1081
 
1078
1082
 
@@ -1773,8 +1777,8 @@ def schema_option_frontend(cfg):
1773
1777
  # Package information
1774
1778
  ############################################
1775
1779
  def schema_package(cfg):
1776
- from siliconcompiler.packageschema import PackageSchema
1777
- cfg.insert("package", PackageSchema())
1780
+ from siliconcompiler.packageschema import PackageSchemaTmp
1781
+ cfg.insert("package", PackageSchemaTmp())
1778
1782
  return cfg
1779
1783
 
1780
1784
 
@@ -9,7 +9,6 @@ from siliconcompiler.schema import SafeSchema
9
9
  from siliconcompiler.schema import EditableSchema
10
10
  from siliconcompiler.schema import CommandLineSchema
11
11
  from siliconcompiler.schema import Parameter
12
- from siliconcompiler.schema.baseschema import json
13
12
 
14
13
  from siliconcompiler.schema.schema_cfg import schema_cfg
15
14
 
@@ -85,6 +84,9 @@ class SchemaTmp(Schema, CommandLineSchema):
85
84
 
86
85
  super()._from_dict(manifest, keypath, version=version)
87
86
 
87
+ def _find_files_dataroot_resolvers(self):
88
+ return self.get("package", field="schema").get_resolvers()
89
+
88
90
  def record_history(self):
89
91
  '''
90
92
  Copies all non-empty parameters from current job into the history
@@ -115,5 +117,5 @@ class SchemaTmp(Schema, CommandLineSchema):
115
117
  ##############################################################################
116
118
  # Main routine
117
119
  if __name__ == "__main__":
118
- import json as main_json
119
- print(main_json.dumps(SchemaTmp().getdict(), indent=4, sort_keys=True))
120
+ import json
121
+ print(json.dumps(SchemaTmp().getdict(), indent=4, sort_keys=True))