zuspec-dataclasses 0.0.1.17421055506rc0__py3-none-any.whl → 0.0.1.18247373596rc0__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 (28) hide show
  1. zuspec/dataclasses/__init__.py +22 -2
  2. zuspec/dataclasses/__version__.py +16 -1
  3. zuspec/dataclasses/action.py +15 -0
  4. zuspec/dataclasses/addr_reg.py +67 -27
  5. zuspec/dataclasses/annotation.py +15 -0
  6. zuspec/dataclasses/api/__init__.py +16 -0
  7. zuspec/dataclasses/api/type_processor.py +26 -0
  8. zuspec/dataclasses/api/visitor.py +296 -16
  9. zuspec/dataclasses/bit.py +17 -5
  10. zuspec/dataclasses/bundle.py +17 -0
  11. zuspec/dataclasses/component.py +49 -2
  12. zuspec/dataclasses/decorators.py +172 -38
  13. zuspec/dataclasses/dependency.py +15 -1
  14. zuspec/dataclasses/ports.py +0 -5
  15. zuspec/dataclasses/std/__init__.py +18 -0
  16. zuspec/dataclasses/std/clock_reset.py +35 -0
  17. zuspec/dataclasses/std/timebase.py +45 -0
  18. zuspec/dataclasses/struct.py +9 -2
  19. zuspec/dataclasses/tlm.py +6 -0
  20. {zuspec_dataclasses-0.0.1.17421055506rc0.dist-info → zuspec_dataclasses-0.0.1.18247373596rc0.dist-info}/METADATA +1 -1
  21. zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/RECORD +29 -0
  22. zuspec/dataclasses/clock.py +0 -3
  23. zuspec/dataclasses/reset.py +0 -3
  24. zuspec/dataclasses/timebase.py +0 -27
  25. zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/RECORD +0 -28
  26. {zuspec_dataclasses-0.0.1.17421055506rc0.dist-info → zuspec_dataclasses-0.0.1.18247373596rc0.dist-info}/WHEEL +0 -0
  27. {zuspec_dataclasses-0.0.1.17421055506rc0.dist-info → zuspec_dataclasses-0.0.1.18247373596rc0.dist-info}/licenses/LICENSE +0 -0
  28. {zuspec_dataclasses-0.0.1.17421055506rc0.dist-info → zuspec_dataclasses-0.0.1.18247373596rc0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,22 @@
1
1
 
2
2
 
3
+ #****************************************************************************
4
+ # Copyright 2019-2025 Matthew Ballance and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #****************************************************************************
3
18
  # from .activity_stmts import *
4
- from .decorators import dataclass, field, export, process, input, output, sync, const, port, export, bind
19
+ from .decorators import dataclass, field, export, extern, process, input, output, sync, const, port, export, bind
5
20
  from .tlm import *
6
21
  # from .claims_refs import *
7
22
  # from .shared_stmts import *
@@ -9,9 +24,14 @@ from .tlm import *
9
24
  # from .core_lib import *
10
25
  # from vsc_dataclasses.expr import *
11
26
 
27
+ from . import std
28
+
12
29
  from .bit import Bit
30
+ from .action import Action
31
+ from .std.clock_reset import ClockReset
13
32
  from .component import Component
14
- from .struct import Struct
33
+ from .exec import ExecSync, Exec
34
+ from .struct import Struct, ZuspecTypeBase
15
35
  from .ports import Input, Output, Port
16
36
 
17
37
  from asyncio import Event
@@ -1,4 +1,19 @@
1
1
 
2
+ #****************************************************************************
3
+ # Copyright 2019-2025 Matthew Ballance and contributors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #****************************************************************************
2
17
  BASE="0.0.1"
3
- SUFFIX=".17421055506rc0"
18
+ SUFFIX=".18247373596rc0"
4
19
  VERSION="%s%s" % (BASE, SUFFIX)
@@ -1,3 +1,18 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  from typing import Self, Type, TypeVar
2
17
  from .decorators import dataclass, field
3
18
  from .component import Component
@@ -1,61 +1,101 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  import abc
2
17
  import zuspec.dataclasses as zdc
3
- from typing import Annotated, TypeVar, Type, Union
18
+ from typing import Annotated, Dict, TypeVar, Type, Union
4
19
  from .struct import StructPacked
5
20
 
21
+ class AddrHandle(): pass
22
+
6
23
  class AddrTrait(zdc.Struct): pass
7
24
 
8
25
 
9
26
  class AddrSpaceBase:
10
27
  pass
11
28
 
12
- uint64_t = Annotated[int, "abc"]
29
+ # uint64_t = Annotated[int, "abc"]
13
30
 
14
31
  AddrTraitT = TypeVar('AddrTraitT', bound=AddrTrait)
15
32
 
33
+ @dataclass
16
34
  class AddrRegion[AddrTraitT]():
17
- trait : Type[AddrTraitT] = zdc.trait()
18
- pass
19
-
20
- class MyTrait(AddrTrait):
21
- a : int = 5
35
+ trait : Type[AddrTraitT] = zdc.field()
22
36
 
37
+ @dataclass
23
38
  class TransparentAddrSpace[AddrTraitT](AddrSpaceBase):
24
39
 
25
- def add_region(self, region : AddrRegion[AddrTraitT]): pass
26
-
27
- pass
28
-
29
- class MyAddrTrait(AddrTrait):
30
- pass
31
-
32
- class Other(object):
33
- pass
40
+ @abc.abstractmethod
41
+ def add_region(self, region : AddrRegion[AddrTraitT]) -> AddrHandle:
42
+ """Adds a region to the address space, returning a handle to that region"""
43
+ pass
34
44
 
35
- t : TransparentAddrSpace = TransparentAddrSpace()
36
- o = Other()
45
+ @dataclass
46
+ class AddrClaim[AddrTraitT]():
47
+ trait : AddrTraitT = zdc.field(rand=True)
48
+ size : int = zdc.field(rand=True)
37
49
 
38
- r = AddrRegion[MyTrait]()
39
- r2 = AddrRegion[Other]()
50
+ @constraint
51
+ def size_align_c(self):
52
+ self.size > 0
40
53
 
41
- t.add_region(r2)
42
54
 
43
- r.trait.a
55
+ @abc.abstractmethod
56
+ def handle(self, offset : int = 0) -> AddrHandle:
57
+ """Returns a handle corresponding to the claim"""
58
+ pass
44
59
 
45
- RegT = TypeVar("RegT", bound=Union[int,StructPacked])
60
+ RegT = TypeVar("RegT", bound=Union[BitVal,StructPacked])
46
61
 
47
62
  class Reg[RegT](object):
48
63
 
49
64
  @abc.abstractmethod
50
- def read(self) -> Type[RegT]: pass
65
+ async def read(self) -> Type[RegT]:
66
+ """Reads the value of the register"""
67
+ pass
51
68
 
52
69
  @abc.abstractmethod
53
- def write(self, data : Type[RegT]): pass
70
+ async def write(self, data : Type[RegT]):
71
+ """Writes the value of the register"""
72
+ pass
73
+
74
+ def write_fields(self, fields : Dict[object,int]): pass
54
75
 
55
76
  class RegGroup(object):
56
77
  @abc.abstractmethod
57
- def get_handle(self): pass
78
+ def get_handle(self) -> AddrHandle:
79
+ """Gets the address handle that corresponds to this group"""
80
+ pass
58
81
 
59
82
  @abc.abstractmethod
60
- def set_handle(self, h): pass
83
+ def set_handle(self, h):
84
+ """Sets the address handle corresponding to this root group"""
85
+ pass
86
+
87
+
88
+ class At(object):
89
+ a : zdc.Bit[15] = zdc.field()
90
+ b : zdc.Bit[15] = zdc.field()
91
+
92
+ # def __int__(self) -> int:
93
+ # pass
94
+
95
+ # r : Reg[At] = 5
96
+ # r.read() == 20
97
+ # r.write()
98
+ # r.write_fields({At.a : 5})
99
+ # def reg(offset=)
61
100
 
101
+ # def reg_array(offset=0, offset_of=lambda i: )
@@ -1,3 +1,18 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  import dataclasses as dc
2
17
  from typing import Callable, ClassVar
3
18
 
@@ -1,2 +1,18 @@
1
1
 
2
+ #****************************************************************************
3
+ # Copyright 2019-2025 Matthew Ballance and contributors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #****************************************************************************
17
+ from .type_processor import TypeProcessor
2
18
  from .visitor import Visitor
@@ -0,0 +1,26 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
16
+ import abc
17
+
18
+ class TypeProcessor(object):
19
+
20
+ @abc.abstractmethod
21
+ def new(self, c, *args, **kwargs):
22
+ pass
23
+
24
+ @abc.abstractmethod
25
+ def init(self, obj, *args, **kwargs):
26
+ pass
@@ -1,14 +1,61 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  import dataclasses as dc
2
- from typing import Callable, ClassVar, Dict, Type
17
+ import logging
18
+ from dataclasses import Field, MISSING
19
+ from typing import Callable, ClassVar, Dict, Type, List, Tuple
3
20
  from ..annotation import Annotation
21
+ from ..bit import Bit
4
22
  from ..component import Component
23
+ from ..exec import Exec, ExecKind, ExecSync
5
24
  from ..ports import Input, Output
6
- from ..struct import Struct
25
+ from ..struct import Extern, Struct
26
+ import inspect
27
+ import ast
28
+ import textwrap
29
+
30
+ class _BindPathMock:
31
+ def __init__(self, typ, path=None):
32
+ self._typ = typ
33
+ self._path = path or []
34
+
35
+ def __getattribute__(self, name):
36
+ if name in ("_typ", "_path", "__class__"):
37
+ return object.__getattribute__(self, name)
38
+ # Validate field exists
39
+ fields = {f.name for f in dc.fields(self._typ)}
40
+ if name not in fields:
41
+ raise AttributeError(f"Invalid field '{name}' in path {'.'.join(self._path + [name])}")
42
+ # Get field type
43
+ field_type = next(f.type for f in dc.fields(self._typ) if f.name == name)
44
+ # Return new mock for nested access
45
+ return _BindPathMock(field_type, self._path + [name])
46
+
47
+ def __call__(self):
48
+ # For supporting callables if needed
49
+ return self
50
+
51
+ def __repr__(self):
52
+ return f"_BindPathMock({self._typ}, {self._path})"
7
53
 
8
54
  @dc.dataclass
9
55
  class Visitor(object):
10
56
  _type_m : Dict[Type,Callable] = dc.field(default_factory=dict)
11
57
  _field_factory_m : Dict[Type,Callable] = dc.field(default_factory=dict)
58
+ _log : ClassVar = logging.getLogger("Visitor")
12
59
 
13
60
  def __post_init__(self):
14
61
  self._type_m = {
@@ -20,41 +67,274 @@ class Visitor(object):
20
67
  }
21
68
 
22
69
  def visit(self, t):
70
+ # Accept both class and instance
71
+ t_cls = t if isinstance(t, type) else type(t)
23
72
  found = False
24
73
  for base_t,method in self._type_m.items():
25
- if issubclass(t, base_t):
74
+ if issubclass(t_cls, base_t):
26
75
  method(t)
27
76
  found = True
28
77
  break
29
78
  if not found:
30
- raise Exception("Unsupported class %s" % str(type(t)))
79
+ raise Exception("Unsupported class %s" % str(t))
31
80
 
32
81
  def visitComponentType(self, t):
33
- self.visitStructType(t)
82
+ # Always work with the class, not the instance
83
+ t_cls = t if isinstance(t, type) else type(t)
84
+ self.visitStructType(t_cls)
34
85
  pass
35
86
 
36
- def visitStructType(self, t : Struct):
87
+ def _elabBindPath(self, path_lambda, root_type):
88
+ """
89
+ Processes a lambda expression returning a single property path.
90
+ Returns: (field_obj, path_tuple)
91
+ """
92
+ root_mock = _BindPathMock(root_type, ["s"])
93
+ result_mock = path_lambda(root_mock)
94
+ path = getattr(result_mock, "_path", None)
95
+ if path is None:
96
+ raise ValueError("Lambda must return a _BindPathMock instance")
97
+ typ = root_type
98
+ for name in path[1:]: # skip 's'
99
+ field = next(f for f in dc.fields(typ) if f.name == name)
100
+ typ = field.type
101
+ return (field, tuple(path))
102
+
103
+ def _elabBinds(self, bind_lambda, root_type):
104
+ # Instantiate mock for root
105
+ root_mock = _BindPathMock(root_type, ["s"])
106
+ # Evaluate lambda to get mapping
107
+ mapping = bind_lambda(root_mock)
108
+ result = {}
109
+ for k, v in mapping.items():
110
+ # Extract path from mock objects
111
+ k_path = getattr(k, "_path", None)
112
+ v_path = getattr(v, "_path", None)
113
+ if k_path is None or v_path is None:
114
+ raise ValueError("Bind keys/values must be _BindPathMock instances")
115
+ # Get terminal Field for key
116
+ k_typ = root_type
117
+ for name in k_path[1:]: # skip 's'
118
+ field = next(f for f in dc.fields(k_typ) if f.name == name)
119
+ k_typ = field.type
120
+ k_field = field
121
+ # Get terminal Field for value
122
+ v_typ = root_type
123
+ for name in v_path[1:]:
124
+ field = next(f for f in dc.fields(v_typ) if f.name == name)
125
+ v_typ = field.type
126
+ v_field = field
127
+ result[(k_field, tuple(k_path))] = (v_field, tuple(v_path))
128
+ return result
129
+
130
+ def _visitFields(self, t : Struct):
131
+ print("--> visitFields")
37
132
  for f in dc.fields(t):
133
+ print("Field: %s" % f.name)
38
134
  self._dispatchField(f)
135
+
136
+ def _dispatchField(self, f : dc.Field):
137
+ if f.default_factory not in (None, dc.MISSING):
138
+ if issubclass(f.default_factory, Input):
139
+ self.visitFieldInOut(f, False)
140
+ elif issubclass(f.default_factory, Output):
141
+ self.visitFieldInOut(f, True)
142
+ elif issubclass(f.default_factory, Exec):
143
+ self.visitExec(f)
144
+ elif issubclass(f.default_factory, Extern):
145
+ self.visitFieldExtern(f)
146
+ else:
147
+ raise Exception("Unknown factory %s" % f.default_factory)
148
+ pass
149
+ elif f.type in (str, int, float):
150
+ self.visitFieldData(f)
151
+ elif issubclass(f.type, Component):
152
+ print("visitFieldClass: Component %s" % f, flush=True)
153
+ self.visitFieldClass(f)
154
+ else:
155
+ print("visitFieldClass: %s" % f, flush=True)
156
+ self.visitFieldClass(f)
157
+
158
+ def _visitExecs(self, t):
159
+ exec_t = (
160
+ (ExecSync, self.visitExecSync),
161
+ (Exec, self.visitExec)
162
+ )
163
+ for n in dir(t):
164
+ o = getattr(t, n)
165
+ for et, em in exec_t:
166
+ if isinstance(o, et):
167
+ em(o)
168
+ break
169
+
170
+ def _visitFunctions(self, t):
171
+ for e in dir(t):
172
+ if not e.startswith("__") and callable(getattr(t, e)):
173
+ print("Function: %s" % e)
174
+ self.visitFunction(getattr(t, e))
175
+
176
+ def visitFunction(self, f):
177
+ pass
178
+
179
+ def _visitDataType(self, t):
180
+
181
+ if t == int:
182
+ self.visitDataTypeInt()
183
+ elif type(t) is type:
184
+ zsp_base_t = (
185
+ (Component, self.visitDataTypeComponent),
186
+ )
187
+
188
+ v = None
189
+ for tt,vv in zsp_base_t:
190
+ print("t: %s tt: %s vv: %s" % (t, tt, vv))
191
+ if issubclass(t, tt):
192
+ v = vv
193
+ break
194
+
195
+ v(t)
196
+ else:
197
+ raise Exception("Unknown type %s" % str(t))
198
+ pass
199
+
200
+ def visitDataTypeComponent(self, t):
201
+ pass
202
+
203
+ def visitDataTypeInt(self):
204
+ pass
205
+
206
+ def visitField(self, f : dc.Field):
207
+ pass
208
+
209
+ def visitFieldClass(self, f : dc.Field):
210
+ self.visitField(f)
211
+
212
+ def visitFieldInOut(self, f : dc.Field, is_out : bool):
213
+ self.visitField(f)
214
+
215
+ def visitFieldData(self, f : dc.Field):
216
+ self.visitField(f)
217
+ self._visitDataType(f.type)
218
+
219
+ def visitStructType(self, t : Struct):
220
+ self._visitFields(t)
221
+ self._visitExecs(t)
39
222
 
40
223
  for f in dir(t):
41
224
  o = getattr(t, f)
42
- if callable(o) and hasattr(o, Annotation.NAME):
43
- self.visitExec(f, o)
44
- print("Found")
225
+ # if callable(o) and hasattr(o, Annotation.NAME):
226
+ # # Extract source code of the method
227
+ # try:
228
+ # src = inspect.getsource(o)
229
+ # src = textwrap.dedent(src)
230
+ # tree = ast.parse(src)
231
+ # for stmt in tree.body[0].body: # tree.body[0] is the FunctionDef
232
+ # self.visit_statement(stmt)
233
+ # except Exception as e:
234
+ # print(f"Could not process method {f}: {e}")
235
+ # # self.visitExec(f, o)
236
+ # # print("Found")
237
+
238
+ def _findFieldRefs(self, t : Struct, method) -> List[Tuple[bool,dc.Field,Tuple[str]]]:
239
+ """
240
+ Processes the body of a Python method to identify class members
241
+ referenced inside.
242
+ Returns: List of [<is_write>,[path]]
243
+ """
244
+ import inspect, ast, textwrap
245
+
246
+ src = inspect.getsource(method)
247
+ src = textwrap.dedent(src)
248
+ tree = ast.parse(src)
249
+ refs = []
250
+
251
+ # Map field names to Field objects
252
+ field_map = {f.name: f for f in dc.fields(t)}
253
+
254
+ class FieldRefVisitor(ast.NodeVisitor):
255
+ def __init__(self):
256
+ self.refs = []
257
+
258
+ def visit_Assign(self, node):
259
+ # Left-hand side: writes
260
+ for target in node.targets:
261
+ if isinstance(target, ast.Attribute) and isinstance(target.value, ast.Name) and target.value.id == "self":
262
+ field = target.attr
263
+ if field in field_map:
264
+ self.refs.append((True, field_map[field], ("self", field)))
265
+ # Right-hand side: reads
266
+ self.visit(node.value)
267
+
268
+ def visit_Attribute(self, node):
269
+ if isinstance(node.value, ast.Name) and node.value.id == "self":
270
+ field = node.attr
271
+ if field in field_map:
272
+ self.refs.append((False, field_map[field], ("self", field)))
273
+ self.generic_visit(node)
274
+
275
+ visitor = FieldRefVisitor()
276
+ for stmt in tree.body[0].body:
277
+ visitor.visit(stmt)
278
+
279
+ # Remove duplicate refs (e.g., multiple reads/writes)
280
+ unique_refs = []
281
+ seen = set()
282
+ for ref in visitor.refs:
283
+ key = (ref[0], ref[1].name, ref[2])
284
+ if key not in seen:
285
+ unique_refs.append(ref)
286
+ seen.add(key)
287
+ return unique_refs
45
288
 
46
- def visitExec(self, name, m):
289
+ def visitExec(self, e : Exec):
47
290
  pass
48
291
 
49
- def _dispatchField(self, f : dc.Field):
50
- if f.default_factory in self._field_factory_m.keys():
51
- self._field_factory_m[f.default_factory](f)
52
- else:
53
- self.visitField(f)
292
+ def visitExecSync(self, e : ExecSync):
293
+ self.visitExec(e)
54
294
 
55
- def visitField(self, f : dc.Field):
295
+ def visitFieldExtern(self, f : dc.Field):
56
296
  pass
57
297
 
298
+ def visitOutputField(self, f : dc.Field):
299
+ self.visitField(f)
300
+
301
+ def visitIntField(self, f : dc.Field):
302
+ self.visitField(f)
303
+
304
+ def visitStrField(self, f : dc.Field):
305
+ self.visitField(f)
306
+
307
+ def visit_statement(self, stmt):
308
+ method = f"visit_{type(stmt).__name__}"
309
+ visitor = getattr(self, method, self.generic_visit)
310
+ return visitor(stmt)
311
+
312
+ def generic_visit(self, stmt):
313
+ # Recursively visit child statements if present
314
+ for field, value in ast.iter_fields(stmt):
315
+ if isinstance(value, list):
316
+ for item in value:
317
+ if isinstance(item, ast.stmt):
318
+ self.visit_statement(item)
319
+ elif isinstance(value, ast.stmt):
320
+ self.visit_statement(value)
321
+
322
+ def visit_Assign(self, stmt: ast.Assign):
323
+ # Example: handle assignment statements
324
+ # Recursively visit child nodes if needed
325
+ self.generic_visit(stmt)
326
+
327
+ def visit_If(self, stmt: ast.If):
328
+ # Example: handle if statements
329
+ for s in stmt.body:
330
+ self.visit_statement(s)
331
+ for s in stmt.orelse:
332
+ self.visit_statement(s)
333
+
334
+ def visit_Expr(self, stmt: ast.Expr):
335
+ # Example: handle expression statements
336
+ self.generic_visit(stmt)
337
+
58
338
  def visitInput(self, f : dc.Field):
59
339
  self.visitField(f)
60
340
  pass
zuspec/dataclasses/bit.py CHANGED
@@ -1,7 +1,12 @@
1
1
  import dataclasses as dc
2
- from typing import Dict
2
+ from typing import Dict, Generic, TypeVar, Literal, Type
3
3
 
4
4
  class BitMeta(type):
5
+ """
6
+ The BitMeta class is a constructor for Bit types.
7
+ Bit[12], for example, produces a Bit type where
8
+ W=12.
9
+ """
5
10
 
6
11
  def __new__(cls, name, bases, attrs):
7
12
  return super().__new__(cls, name, bases, attrs)
@@ -15,12 +20,19 @@ class BitMeta(type):
15
20
  return self.type_m[W]
16
21
  else:
17
22
  t = type("bit[%d]" % W, (Bit,), {
18
- "T" : W
23
+ "W" : W
19
24
  })
20
25
  self.type_m[W] = t
21
26
  return t
22
27
 
23
-
24
28
  class Bit(metaclass=BitMeta):
25
- T : int = 1
26
- pass
29
+ """
30
+ Variables of 'Bit' type represent unsigned W-bit values.
31
+ The value of the variables is automatically masked. For
32
+ example, assigning 20 (b10100) to a 4-bit variable will
33
+ result in 4 (b0100) being stored in the variable.
34
+ """
35
+ W : int = 1
36
+
37
+ class Bits(metaclass=BitMeta):
38
+ W : int = -1
@@ -1,3 +1,18 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  from typing import Annotated, Type, TypeVar
2
17
  from .decorators import dataclass
3
18
 
@@ -11,6 +26,8 @@ class Bundle(object):
11
26
  fields are created with mirror() or field(mirror=True)
12
27
 
13
28
  A bundle field can be connected to a mirror field.
29
+ A bundle monitor field can be connected to both a
30
+ bundle and a bundle mirror.
14
31
  - Bundle
15
32
  - Bundle Mirror
16
33
  - Bundle Monitor (all are inputs / exports)
@@ -1,6 +1,26 @@
1
- from .decorators import dataclass
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
16
+ import abc
17
+ from typing import TYPE_CHECKING
18
+ from .decorators import dataclass, field
2
19
  from .struct import Struct
3
20
 
21
+ if TYPE_CHECKING:
22
+ from .std.timebase import TimeBase
23
+
4
24
  @dataclass
5
25
  class Component(Struct):
6
26
  """
@@ -9,7 +29,34 @@ class Component(Struct):
9
29
  - The root component and fields of component type are constructed
10
30
  - The 'init_down' method is invoked in a depth-first manner
11
31
  - The 'init_up' method is invoked
32
+
33
+ A Component class supports the following decorated methods:
34
+ - sync
35
+ - constraint
36
+ - activity
12
37
  """
38
+ # def build(self): pass
39
+
40
+ @abc.abstractmethod
41
+ async def wait(self, amt : float, units):
42
+ """
43
+ Uses the default timebase to suspend execution of the
44
+ calling coroutine for the specified time.
45
+ """
46
+ pass
13
47
 
14
- def build(self): pass
48
+ @abc.abstractmethod
49
+ async def wait_next(self, count : int = 1):
50
+ """
51
+ Uses the default timebase to suspend execution of the
52
+ calling coroutine for the specified number of domain
53
+ evaluation events (eg clock cycles).
54
+ """
55
+ pass
15
56
 
57
+ @dataclass
58
+ class ComponentExtern(Component):
59
+ """
60
+ Extern components are used to interface with existing descriptions,
61
+ such as existing Verilog RTL.
62
+ """
@@ -1,31 +1,60 @@
1
- '''
2
- Created on Mar 19, 2022
3
-
4
- @author: mballance
5
- '''
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # Created on Mar 19, 2022
17
+ # @author: mballance
18
+ #****************************************************************************
6
19
  import dataclasses
7
20
  import dataclasses as dc
8
- from typing import Any, Callable, Dict, Self, TypeVar
9
- # from vsc_dataclasses.decorators import *
10
- # from .impl.action_decorator_impl import ActionDecoratorImpl
11
- # from .impl.exec_decorator_impl import ExecDecoratorImpl
12
- # from .impl.exec_kind_e import ExecKindE
13
- # from .impl.extend_kind_e import ExtendKindE
14
- # from .impl.extend_decorator_impl import ExtendDecoratorImpl
15
- # from .impl.extend_action_decorator_impl import ExtendActionDecoratorImpl
16
- # from .impl.extend_component_decorator_impl import ExtendComponentDecoratorImpl
17
- # from .impl.fn_decorator_impl import FnDecoratorImpl
18
- # from .impl.struct_decorator_impl import StructDecoratorImpl
19
- # from .impl.struct_kind_e import StructKindE
20
- # from .impl.component_decorator_impl import ComponentDecoratorImpl
21
- # from .impl.activity_decorator_impl import ActivityDecoratorImpl
22
- # from .impl.type_kind_e import TypeKindE
21
+ import enum
22
+ import inspect
23
+ import typing
24
+ from typing import Any, Callable, Dict, Optional, Self, TypeVar, TYPE_CHECKING, Union
23
25
  from .annotation import Annotation, AnnotationSync
24
- from .ports import Input, Output
25
- from .clock import Clock
26
+
27
+
28
+ if TYPE_CHECKING:
29
+ from .api.type_processor import TypeProcessor
26
30
 
27
31
  def dataclass(cls, **kwargs):
28
- return dc.dataclass(cls, **kwargs)
32
+ # TODO: Add type annotations to decorated methods
33
+ cls_annotations = cls.__annotations__
34
+
35
+ for name, value in cls.__dict__.items():
36
+ # print("Name: %s ; Value: %s" % (name, value))
37
+ if isinstance(value, dc.Field) and not name in cls_annotations:
38
+ print("TODO: annotate field")
39
+ cls_annotations[name] = int
40
+
41
+ cls_t = dc.dataclass(cls, **kwargs)
42
+
43
+ setattr(cls_t, "__base_init__", getattr(cls_t, "__init__"))
44
+ def local_init(self, tp : 'TypeProcessor', *args, **kwargs):
45
+ """Only called during type processing"""
46
+ return tp.init(self, *args, **kwargs)
47
+ setattr(cls_t, "__init__", local_init)
48
+
49
+ if not hasattr(cls_t, "__base_new__"):
50
+ setattr(cls_t, "__base_new__", getattr(cls_t, "__new__"))
51
+ def local_new(c, tp : 'TypeProcessor', *args, **kwargs):
52
+ """Always called during user-object construction"""
53
+ return tp.new(c, *args, **kwargs)
54
+ setattr(cls_t, "__new__", local_new)
55
+
56
+
57
+ return cls_t
29
58
 
30
59
  def bundle():
31
60
  return dc.field()
@@ -94,8 +123,9 @@ def always(instr : BitLiteral):
94
123
  a = bit(20)[3:4]
95
124
 
96
125
  SelfT = TypeVar('SelfT')
126
+ T = TypeVar('T')
97
127
 
98
- class bind[T](object):
128
+ class bind[T]:
99
129
  def __init__(self, c : Callable[[T],Dict[Any,Any]]):
100
130
  self._c = c
101
131
  def __call__(self, s) -> Dict[Any,Any]:
@@ -103,8 +133,49 @@ class bind[T](object):
103
133
 
104
134
  #a = bind2(lambda s:{s.}, selfT=Self)
105
135
 
106
- def field(rand=False, bind : Callable[[object],Dict[Any,Any]] = None):
107
- pass
136
+ def field(
137
+ rand=False,
138
+ bind : Optional[Callable[[object],Dict[Any,Any]]] = None,
139
+ init : Optional[Union[Dict[str,Any], Callable[[object],Dict[Any,Any]]]] = None,
140
+ default_factory : Optional[Any] = None,
141
+ default : Optional[Any] = None):
142
+ args = {}
143
+ metadata = None
144
+
145
+ # # Obtain the location of this call
146
+ # import inspect
147
+ # frame = inspect.currentframe()
148
+ # print("--> ")
149
+ # while frame is not None:
150
+ # modname = frame.f_globals["__name__"]
151
+
152
+ # print("modname: %s" % modname)
153
+ # if not modname.startswith("zuspec.dataclasses") and not modname.startswith("importlib"):
154
+ # break
155
+ # # pass
156
+ # # frame = frame.f_back
157
+ # else:
158
+ # frame = frame.f_back
159
+ # print("<-- ")
160
+
161
+ # if frame is not None:
162
+ # print("Location: %s:%d" % (frame.f_code.co_filename, frame.f_lineno))
163
+
164
+ if default_factory is not None:
165
+ args["default_factory"] = default_factory
166
+
167
+ if bind is not None:
168
+ metadata = {} if metadata is None else metadata
169
+ metadata["bind"] = bind
170
+
171
+ # *Always* specify a default to avoid becoming a required field
172
+ if "default_factory" not in args.keys():
173
+ args["default"] = default
174
+
175
+ if metadata is not None:
176
+ print("metadata: %s" % metadata)
177
+ args["metadata"] = metadata
178
+ return dc.field(**args)
108
179
 
109
180
  # @staticmethod
110
181
  # def __call__(rand=False, bind : Callable[[T],Dict[Any,Any]] = None):
@@ -118,10 +189,26 @@ def field(rand=False, bind : Callable[[object],Dict[Any,Any]] = None):
118
189
  # # TODO:
119
190
  # return dc.field()
120
191
 
192
+ class Input(object): pass
193
+
194
+ class Output(object): pass
195
+
121
196
  def input(*args, **kwargs):
197
+ """
198
+ Marks an input field. Input fields declared on a
199
+ top-level component are `bound` to an implicit output. Those
200
+ on non-top-level components must explicitly be `bound` to an
201
+ output. An input field sees the value of the output field
202
+ to which it is bound with no delay
203
+ """
122
204
  return dataclasses.field(default_factory=Input)
123
205
 
124
206
  def output(*args, **kwargs):
207
+ """
208
+ Marks an output field. Input fields that are bound to
209
+ an output field always see its current output value
210
+ with no delay.
211
+ """
125
212
  return dc.field(default_factory=Output)
126
213
 
127
214
  def lock(*args, **kwargs):
@@ -136,26 +223,73 @@ def port():
136
223
  def export(*args, bind=None, **kwargs):
137
224
  return dc.field(*args, **kwargs)
138
225
 
226
+ class ExecKind(enum.Enum):
227
+ Comb = enum.auto()
228
+ Sync = enum.auto()
229
+ Proc = enum.auto()
230
+
231
+ @dc.dataclass
232
+ class Exec(object):
233
+ method : Callable = dc.field()
234
+ kind : ExecKind = dc.field()
235
+ timebase : Optional[Callable] = field(default=None)
236
+ t : Optional[Callable] = field(default=None)
237
+
238
+ def extern(
239
+ typename,
240
+ bind,
241
+ files=None,
242
+ params=None):
243
+ """
244
+ Denotes an instance of an external module
245
+ """
246
+ from .struct import Extern
247
+ return dc.field(default_factory=Extern,
248
+ metadata=dict(
249
+ typename=typename,
250
+ bind=bind,
251
+ files=files,
252
+ params=params))
253
+
139
254
  def process(T):
140
- return T
255
+ """
256
+ Marks an always-running process. The specified
257
+ method must be `async` and take no arguments
258
+ """
259
+ return Exec(T, ExecKind.Proc)
141
260
 
142
261
  def reg(offset=0):
143
262
  return dc.field()
144
263
  pass
145
264
 
146
- def const(**kwargs):
265
+ def const(default=None):
147
266
  return dc.field()
148
267
 
149
- def sync(*args, clock=None, reset=None):
150
- # TODO: handle two forms
151
- if len(args) == 0:
152
- def __call__(T):
153
- Annotation.apply(T, AnnotationSync(clock=clock, reset=reset))
154
- return T
155
- return __call__
156
- else:
157
- Annotation.apply(args[0], AnnotationSync(clock=clock, reset=reset))
158
- return args[0]
268
+ @dc.dataclass
269
+ class ExecSync(Exec):
270
+ clock : Optional[Callable] = field(default=None)
271
+ reset : Optional[Callable] = field(default=None)
272
+
273
+ def sync(clock : Callable, reset : Callable):
274
+ """
275
+ Marks a synchronous-evaluation region, which is evaluated on
276
+ the active edge of either the clock or reset.
277
+ Assignments are delayed/nonblocking, which means that only
278
+ the last assignment to a variable takes effect.
279
+ """
280
+ def __call__(T):
281
+ return ExecSync(method=T, kind=ExecKind.Sync, clock=clock, reset=reset)
282
+ return __call__
283
+
284
+ def comb(latch : bool=False):
285
+ """
286
+ Marks a combinational evaluation region that is evaluated
287
+ whenever one of the variables read by the method changes.
288
+ """
289
+ def __call__(T):
290
+ return Exec(method=T, kind=ExecKind.Comb, )
291
+ return __call__
292
+
159
293
 
160
294
  # def action(*args, **kwargs):
161
295
  # if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
@@ -1,3 +1,18 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
1
16
  import abc
2
17
  import dataclasses as dc
3
18
  from typing import List
@@ -19,4 +34,3 @@ class TrackingDependencyProvider[T](DependencyProvider):
19
34
  List of dependencies bound to this provider
20
35
  """
21
36
  pass
22
-
@@ -54,8 +54,3 @@ class Port[T]():
54
54
  # a = self.dat_o().get()
55
55
  # self.dat_o().put(5)
56
56
 
57
- class Input(object):
58
- pass
59
-
60
- class Output(object):
61
- pass
@@ -0,0 +1,18 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
16
+
17
+ from .clock_reset import ClockReset
18
+ from .timebase import TimeBase, TimebaseSync
@@ -0,0 +1,35 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
16
+ import abc
17
+ from ..component import Component
18
+ from ..decorators import dataclass, field, output
19
+ from ..bit import Bit
20
+
21
+ @dataclass
22
+ class ClockReset(Component):
23
+ period : int = field(default=10)
24
+ clock : Bit = output()
25
+ reset : Bit = output()
26
+
27
+ @abc.abstractmethod
28
+ def assert_reset(self): pass
29
+
30
+ @abc.abstractmethod
31
+ def release_reset(self): pass
32
+
33
+ @abc.abstractmethod
34
+ async def next(self, count : int = 1):
35
+ pass
@@ -0,0 +1,45 @@
1
+ #****************************************************************************
2
+ # Copyright 2019-2025 Matthew Ballance and contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #****************************************************************************
16
+ import abc
17
+ from typing import Protocol, TYPE_CHECKING
18
+ from ..decorators import dataclass
19
+ from ..bit import Bit
20
+ from ..component import Component
21
+
22
+ class TimeBase(Protocol):
23
+ """
24
+ TimeBase exposes the notion of design time
25
+ """
26
+
27
+ @abc.abstractmethod
28
+ async def wait(self, amt : float, units):
29
+ """Scales the time to the timebase and waits"""
30
+ ...
31
+
32
+
33
+ @abc.abstractmethod
34
+ def wait_ev(self, amt : float, units):
35
+ """Scales the time to the timebase and returns an event"""
36
+ ...
37
+
38
+ @dataclass
39
+ class TimebaseSync(TimeBase):
40
+
41
+ @abc.abstractmethod
42
+ async def wait_next(self, count : int = 1):
43
+ """Waits for 'count' timebase events (eg clocks)"""
44
+ ...
45
+
@@ -3,7 +3,11 @@ from typing import Dict, Optional, Type
3
3
  from .decorators import dataclass
4
4
 
5
5
  @dataclass
6
- class StructPacked(object):
6
+ class ZuspecTypeBase(object):
7
+ pass
8
+
9
+ @dataclass
10
+ class StructPacked(ZuspecTypeBase):
7
11
  """
8
12
  StructPacked types are fixed-size data structures.
9
13
  Fields may only be of a fixed size.
@@ -15,7 +19,7 @@ class StructPacked(object):
15
19
  pass
16
20
 
17
21
  @dataclass
18
- class Struct(object):
22
+ class Struct(ZuspecTypeBase):
19
23
  """
20
24
  Struct types are data structures that may contain
21
25
  variable-size fields.
@@ -26,6 +30,7 @@ class Struct(object):
26
30
  - method
27
31
  """
28
32
 
33
+
29
34
  # @abc.abstractmethod
30
35
  # def bind[T](self, t : T):
31
36
  # t : Type[T],
@@ -40,3 +45,5 @@ class Struct(object):
40
45
  # pass
41
46
 
42
47
  pass
48
+
49
+ class Extern(ZuspecTypeBase): pass
zuspec/dataclasses/tlm.py CHANGED
@@ -10,3 +10,9 @@ class IPut[T]():
10
10
  class IGet[T]():
11
11
  get : Callable[[], Awaitable[T]] = dc.field()
12
12
 
13
+ @dc.dataclass
14
+ class IReqRsp[ReqT,RspT]():
15
+ put : Callable[[Type[ReqT]], Awaitable] = dc.field()
16
+ get : Callable[[], Awaitable[RspT]] = dc.field()
17
+
18
+
@@ -1,5 +1,5 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zuspec-dataclasses
3
- Version: 0.0.1.17421055506rc0
3
+ Version: 0.0.1.18247373596rc0
4
4
  License-File: LICENSE
5
5
  Dynamic: license-file
@@ -0,0 +1,29 @@
1
+ zuspec/dataclasses/__init__.py,sha256=PLcLoAnWVu-Dqz_mYg8pTZoQ3UuN_EHBnY20m7f8YDk,1353
2
+ zuspec/dataclasses/__version__.py,sha256=w6m6NGjqBy7gs-fG-V3ph2_sw4z-KMRNjIjFqN185gI,829
3
+ zuspec/dataclasses/action.py,sha256=12n8lihUhX0BFPcW370IlPgyEXLUMDSDQ_h_-rZr7ik,1328
4
+ zuspec/dataclasses/addr_reg.py,sha256=yKENXgCf9E5VEbfj0qCcJS-fwnQGdSaXG7t00aqA784,2759
5
+ zuspec/dataclasses/annotation.py,sha256=m_3h065RAR81skrq39wxsJ1V0BxpwiyAWzdTrvW51Gg,1086
6
+ zuspec/dataclasses/bit.py,sha256=qBTt8mj_S4WK6VeRaaqeNzzuvy3P12WigKaeU2Gr0mw,1072
7
+ zuspec/dataclasses/bundle.py,sha256=YIuEQS_4oS3LWQ3Zv3Ib78L6V6QzhDsd2S89BP0dsl8,1626
8
+ zuspec/dataclasses/component.py,sha256=yXSmg87uj_1TaazO99mLv72Z0lAlzzQiBTmn0wI5alo,2056
9
+ zuspec/dataclasses/decorators.py,sha256=gsVQ_84GMjfQgETH1nFK1rW4CbG6ab1yt2eJvxbo8q4,13947
10
+ zuspec/dataclasses/dependency.py,sha256=LukfqqvTUfShrtYdidqZeVMie-l50oAzkpYqo_bqie0,1289
11
+ zuspec/dataclasses/ports.py,sha256=OydeAfPIAef8pCp_3FhL87fq7mrbhiNLa9qfPHkCK1E,1044
12
+ zuspec/dataclasses/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
13
+ zuspec/dataclasses/struct.py,sha256=_7Lgf2BbF_WQXSpdKmowR6mATBjqZtqK6VoPPc1tdLg,1077
14
+ zuspec/dataclasses/tlm.py,sha256=sbAlnkYhVidinbiMKBT_mbe5yr1dDU9F_6aKBAXZjjE,431
15
+ zuspec/dataclasses/api/__init__.py,sha256=YwPniS7IHooW5iFCfV2MzKCVf4c4LR7--5SlGOjvGec,830
16
+ zuspec/dataclasses/api/type_processor.py,sha256=4VqIbj-Uo_DqNJpENSq8k5ll5TxhRFlLjq5Psi0Ss7I,956
17
+ zuspec/dataclasses/api/visitor.py,sha256=CduJ6k11xY81_nFl8k0dVSRJt88a21mHem64Yeg6sDI,11852
18
+ zuspec/dataclasses/std/__init__.py,sha256=7xOZCDuEikfg5NRpC0eFGIvgj3hHz7ibtJawzroU4nY,839
19
+ zuspec/dataclasses/std/clock_reset.py,sha256=AveFnqB-OAgWfVr2eA7v9XfAPuE12WtQpSbbE1zhwME,1205
20
+ zuspec/dataclasses/std/timebase.py,sha256=kgkeJ52jHvngdcs8lw5bJ20NDhWmzcAlRmPQ11Qa96A,1468
21
+ zuspec/dataclasses/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ zuspec/dataclasses/util/extract_cpp_embedded_dsl.py,sha256=SyMMLumZD6fsubj40hyekYzWyrcoUGTijJH3NmK1ihY,5630
23
+ zuspec/dataclasses/util/gen_cpp_dt_defs/__main__.py,sha256=t3CnHJKcN_N33sxCsDH-R36ghCcQ7xjMcjUrzUT2SGM,3447
24
+ zuspec/impl/__init__.py,sha256=GZWCeBPdVzLR0RNPkmXNXPgdS-2vg5dMC1goTYJs3yI,33
25
+ zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/METADATA,sha256=O74TphkBnh2iHRNubkDsL_at148MqH3qS_f-HGXQwKY,121
27
+ zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/top_level.txt,sha256=3WM_V5g1RvpI4_z1TPY_AmroKhWIp6QJo4Vz5Tqbgak,7
29
+ zuspec_dataclasses-0.0.1.18247373596rc0.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
-
2
- class Clock(object):
3
- pass
@@ -1,3 +0,0 @@
1
-
2
- class Reset(object):
3
- pass
@@ -1,27 +0,0 @@
1
- import abc
2
- from .component import Component
3
- from .decorators import dataclass, input
4
- from .bit import Bit
5
-
6
- @dataclass
7
- class TimeBase(object):
8
- """
9
- TimeBase exposes the notion of design time
10
- """
11
-
12
- @abc.abstractmethod
13
- async def wait(self, amt : float, units):
14
- """Scales the time to the timebase and waits"""
15
- pass
16
-
17
- @abc.abstractmethod
18
- def wait_ev(self, amt : float, units):
19
- """Scales the time to the timebase and returns an event"""
20
- pass
21
-
22
- pass
23
-
24
- class TimeBaseSignal(TimeBase,Component):
25
- clock : Bit = input()
26
- reset : Bit = input()
27
-
@@ -1,28 +0,0 @@
1
- zuspec/dataclasses/__init__.py,sha256=N7A7kcH2MWv11kqVA-s0SyKnWBAKD6ijQXJOrzfRyf8,452
2
- zuspec/dataclasses/__version__.py,sha256=w206wPrAQOLdhYE50Ud54WEWjFUOPqdoT2NoUpjn64o,71
3
- zuspec/dataclasses/action.py,sha256=z7aMc6e_k_-NCzYDm8K1ymEPfcGeyqlO79of0Gucack,570
4
- zuspec/dataclasses/addr_reg.py,sha256=QmxPQ8lq1255ZfOjQRGFGWGGwK-pSpPFJ4mdzJlj8dw,1111
5
- zuspec/dataclasses/annotation.py,sha256=M41iS93Oi8M-ER_ZIBI8CIWJ1bvEMI0nHa-RxbmWJUs,328
6
- zuspec/dataclasses/bit.py,sha256=Zxm3F04GcfuJczmwCrMuvpcBCunWMZQFffB4JvNterI,614
7
- zuspec/dataclasses/bundle.py,sha256=6fqjfoTS_-_izl4FlPFgurfOg3tnj_1fmEdSa1FF4C0,781
8
- zuspec/dataclasses/clock.py,sha256=pM0rO-3bp0SGJccxtU-17vIcF9EaSlqD-q1_9O0of1o,30
9
- zuspec/dataclasses/component.py,sha256=vzPCmLdAgm-x46Or18RtBYRClVUkbqIZ1yqp1nu5sL4,416
10
- zuspec/dataclasses/decorators.py,sha256=fSJpsTbahzQdtFtlVhDFSHFFuYmiRxg_3S_W1DpjLDY,9797
11
- zuspec/dataclasses/dependency.py,sha256=kGxdFqKlviUP7qmvN-FbnXIiqCPdgRRel83feuu8OoU,532
12
- zuspec/dataclasses/ports.py,sha256=3pbBwdBzDMAJTZ15Qf6sSXB-XOH5cJ-G5H8kQa5JurQ,1106
13
- zuspec/dataclasses/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
14
- zuspec/dataclasses/reset.py,sha256=DV8tiKq_k-AGUNBbpJCJFx_EEfA07UgUJK2veYli0b0,30
15
- zuspec/dataclasses/struct.py,sha256=vId0487ZJmhnTbTg421B-iN9PtxNexCv9DMqRO8RXBU,973
16
- zuspec/dataclasses/timebase.py,sha256=rjEiGB2lNPMTewE-Z4iX-CHnbx1QVTUbtwEXnKMkesI,599
17
- zuspec/dataclasses/tlm.py,sha256=TjODFwvombQR7AVVI7HlW37MEm22Zu9JdVYpOCU4_Vg,277
18
- zuspec/dataclasses/api/__init__.py,sha256=HfJhJ_B1RJSpJn5NmWzEK3l2IruubiEKd3xwLDuED6Q,30
19
- zuspec/dataclasses/api/visitor.py,sha256=8-5er0GxAWnvxhDmiR_OBn2iMxtymtol5qM09ucKdLI,1780
20
- zuspec/dataclasses/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- zuspec/dataclasses/util/extract_cpp_embedded_dsl.py,sha256=SyMMLumZD6fsubj40hyekYzWyrcoUGTijJH3NmK1ihY,5630
22
- zuspec/dataclasses/util/gen_cpp_dt_defs/__main__.py,sha256=t3CnHJKcN_N33sxCsDH-R36ghCcQ7xjMcjUrzUT2SGM,3447
23
- zuspec/impl/__init__.py,sha256=GZWCeBPdVzLR0RNPkmXNXPgdS-2vg5dMC1goTYJs3yI,33
24
- zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
25
- zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/METADATA,sha256=EZDxpqEdg2prfw4jvirp2j5sMETTp0ICrvue99A-Q44,121
26
- zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/top_level.txt,sha256=3WM_V5g1RvpI4_z1TPY_AmroKhWIp6QJo4Vz5Tqbgak,7
28
- zuspec_dataclasses-0.0.1.17421055506rc0.dist-info/RECORD,,