CIRCT 23.0.0git
Loading...
Searching...
No Matches
test_types.py
Go to the documentation of this file.
1import pytest
2
3import esiaccel.types as types
4
5
7 void_type = types.VoidType("void")
8 assert void_type is not None
9 assert isinstance(void_type, types.VoidType)
10
11 bits_type = types.BitsType("bits8", 8)
12 assert bits_type is not None
13 assert isinstance(bits_type, types.BitsType)
14
15 uint_type = types.UIntType("uint32", 32)
16 assert uint_type is not None
17 assert isinstance(uint_type, types.UIntType)
18
19 sint_type = types.SIntType("sint8", 8)
20 assert sint_type is not None
21 assert isinstance(sint_type, types.SIntType)
22 assert sint_type.bit_width == 8
23
24 struct_type = types.StructType(
25 "mystruct",
26 [("field1", types.UIntType("uint8", 8)),
27 ("field2", types.UIntType("uint16", 16))],
28 )
29 assert struct_type is not None
30 assert isinstance(struct_type, types.StructType)
31 field_map = {name: field_type for name, field_type in struct_type.fields}
32 assert isinstance(field_map["field1"], types.UIntType)
33 assert isinstance(field_map["field2"], types.UIntType)
34
35 array_type = types.ArrayType("uint8_array", types.UIntType("uint8", 8), 10)
36 assert array_type is not None
37 assert isinstance(array_type, types.ArrayType)
38 assert hasattr(array_type, "element_type")
39 assert isinstance(array_type.element_type, types.UIntType)
40 assert hasattr(array_type, "size")
41 assert array_type.size == 10
42
43 any_type = types.AnyType("any")
44 assert any_type is not None
45 assert isinstance(any_type, types.AnyType)
46 valid, reason = any_type.is_valid(0)
47 assert not valid
48 assert "any type" in reason
49 assert any_type.bit_width == -1
50 try:
51 any_type.serialize(0)
52 except ValueError as exc:
53 assert "any type" in str(exc)
54 else:
55 assert False, "AnyType.serialize should raise"
56
57 alias_inner = types.UIntType("alias_inner", 16)
58 type_alias = types.TypeAlias("alias_scope", "aliasName", alias_inner)
59 assert type_alias is not None
60 assert isinstance(type_alias, types.TypeAlias)
61 assert type_alias.name == "aliasName"
62 assert isinstance(type_alias.inner_type, types.UIntType)
63 assert type_alias.bit_width == alias_inner.bit_width
64 alias_valid, alias_reason = type_alias.is_valid(42)
65 inner_valid, inner_reason = alias_inner.is_valid(42)
66 assert alias_valid == inner_valid
67 assert alias_reason == inner_reason
68 serialized = type_alias.serialize(42)
69 inner_serialized = alias_inner.serialize(42)
70 assert serialized == inner_serialized
71 assert type_alias.deserialize(serialized) == alias_inner.deserialize(
72 serialized)
73 assert str(type_alias) == "aliasName"
74
75
77 uint8 = types.UIntType("uint8", 8)
78 uint16 = types.UIntType("uint16", 16)
79
80 union_type = types.UnionType("myunion", [("a", uint8), ("b", uint16)])
81 assert union_type is not None
82 assert isinstance(union_type, types.UnionType)
83 assert union_type.bit_width == 16
84
85 field_map = {name: ty for name, ty in union_type.fields}
86 assert isinstance(field_map["a"], types.UIntType)
87 assert isinstance(field_map["b"], types.UIntType)
88
89 # is_valid: single active field
90 valid, reason = union_type.is_valid({"a": 42})
91 assert valid, reason
92 valid, reason = union_type.is_valid({"b": 1000})
93 assert valid, reason
94
95 # is_valid: wrong number of fields
96 valid, reason = union_type.is_valid({"a": 1, "b": 2})
97 assert not valid
98 assert "exactly 1" in reason
99
100 # is_valid: unknown field
101 valid, reason = union_type.is_valid({"c": 1})
102 assert not valid
103 assert "unknown" in reason
104
105 # is_valid: not a dict
106 valid, reason = union_type.is_valid(42)
107 assert not valid
108
109 # serialize / deserialize round-trip through field "a"
110 # Padding is at LSB (beginning of byte stream), data at MSB (end).
111 serialized_a = union_type.serialize({"a": 42})
112 assert len(serialized_a) == 2 # padded to 16-bit union width
113 # Field "a" is 1 byte; padding byte comes first, data byte second.
114 assert serialized_a[0] == 0 # padding byte
115 assert serialized_a[1] == 42 # data byte
116 (deserialized, remaining) = union_type.deserialize(serialized_a)
117 assert remaining == bytearray()
118 assert "a" in deserialized
119 assert "b" in deserialized
120 assert deserialized["a"] == 42
121
122 # serialize / deserialize round-trip through field "b"
123 # Field "b" is 2 bytes (full width), no padding needed.
124 serialized_b = union_type.serialize({"b": 0x1234})
125 assert len(serialized_b) == 2
126 assert serialized_b == bytearray([0x34, 0x12]) # little-endian, no padding
127 (deserialized_b, remaining_b) = union_type.deserialize(serialized_b)
128 assert remaining_b == bytearray()
129 assert deserialized_b["b"] == 0x1234
130
131
133 """Union padding places struct data at MSB when field is narrower."""
134 uint8 = types.UIntType("uint8", 8)
135 uint32 = types.UIntType("uint32", 32)
136 small_struct = types.StructType("!hw.struct<x: ui8, y: ui8>", [("x", uint8),
137 ("y", uint8)])
138 union_type = types.UnionType("myunion2", [("wide", uint32),
139 ("narrow", small_struct)])
140 assert union_type.bit_width == 32
141
142 # Serializing via "narrow" (16 bits) into a 32-bit union:
143 # 2 bytes padding at start, then 2 bytes of struct data.
144 serialized = union_type.serialize({"narrow": {"x": 0xAA, "y": 0xBB}})
145 assert len(serialized) == 4
146 assert serialized[0] == 0 # padding
147 assert serialized[1] == 0 # padding
148 # Struct data occupies the last 2 bytes.
149 assert serialized[2:] != bytearray(2)
150
151 # Deserializing recovers the struct from the MSB portion.
152 (result, leftover) = union_type.deserialize(serialized)
153 assert leftover == bytearray()
154 assert result["narrow"] == {"x": 0xAA, "y": 0xBB}
155
156
158 element_type = types.UIntType("ui8", 8)
159 list_type = types._get_esi_type(
160 types.cpp.ListType("!esi.list<ui8>", element_type.cpp_type))
161
162 assert isinstance(list_type, types.ListType)
163 assert isinstance(list_type.element_type, types.UIntType)
164 assert list_type.element_type.id == element_type.id
165 assert list_type.bit_width == -1
166
167 supports_host, reason = list_type.supports_host
168 assert not supports_host
169 assert reason == "list types require an enclosing window encoding"
170
171 valid, invalid_reason = list_type.is_valid([0x12, 0x34])
172 assert valid
173 assert invalid_reason is None
174
175 valid, invalid_reason = list_type.is_valid("not a list")
176 assert not valid
177 assert "must be a list" in invalid_reason
178
179 valid, invalid_reason = list_type.is_valid([0x12, 0x1FF])
180 assert not valid
181 assert invalid_reason == "invalid element 1: out of range: 511"
182
183 with pytest.raises(ValueError, match="cannot be serialized without a window"):
184 list_type.serialize([0x12, 0x34])
185
186 with pytest.raises(ValueError,
187 match="cannot be deserialized without a window"):
188 list_type.deserialize(bytearray([0x12, 0x34]))
189
190
192 uint8 = types.UIntType("ui8", 8)
193 into_type = types.StructType("!hw.struct<header: ui8, data: ui8>",
194 [("header", uint8), ("data", uint8)])
195 header_type = types.StructType("!hw.struct<header: ui8>", [("header", uint8)])
196 data_type = types.StructType("!hw.struct<data: ui8>", [("data", uint8)])
197 lowered_type = types.UnionType(
198 "!hw.union<header: !hw.struct<header: ui8>, data: !hw.struct<data: ui8>>",
199 [("header", header_type), ("data", data_type)])
200 window_type = types.WindowType(
201 '!esi.window<"test_window", !hw.struct<header: ui8, data: ui8>, '
202 '[<"header", [<"header">]>, <"data", [<"data">]>]>',
203 "test_window",
204 into_type,
205 lowered_type,
206 [
207 types.WindowType.Frame("header",
208 [types.WindowType.Field("header", 0, 0)]),
209 types.WindowType.Frame("data",
210 [types.WindowType.Field("data", 0, 0)]),
211 ],
212 )
213
214 supports_host, reason = window_type.supports_host
215 assert not supports_host
216 assert reason is not None
217 assert "not yet supported" in reason
218
219 valid, invalid_reason = window_type.is_valid({"header": 1, "data": 2})
220 assert not valid
221 assert invalid_reason == reason
222
223 with pytest.raises(ValueError, match="not yet supported"):
224 window_type.serialize({"header": 1, "data": 2})
225
226 with pytest.raises(ValueError, match="not yet supported"):
227 window_type.deserialize(bytearray([1, 2]))
test_union_type()
Definition test_types.py:76
test_list_type_not_supported_for_host()
test_union_padding_with_struct()
test_window_type_not_supported_for_host()