4 from ..hdl
.ast
import *
8 class UnsignedEnum(Enum
):
14 class SignedEnum(Enum
):
20 class StringEnum(Enum
):
25 class ShapeTestCase(FHDLTestCase
):
28 self
.assertEqual(s1
.width
, 1)
29 self
.assertEqual(s1
.signed
, False)
30 s2
= Shape(signed
=True)
31 self
.assertEqual(s2
.width
, 1)
32 self
.assertEqual(s2
.signed
, True)
34 self
.assertEqual(s3
.width
, 3)
35 self
.assertEqual(s3
.signed
, True)
37 def test_make_wrong(self
):
38 with self
.assertRaises(TypeError,
39 msg
="Width must be a non-negative integer, not -1"):
43 width
, signed
= Shape()
44 self
.assertEqual(width
, 1)
45 self
.assertEqual(signed
, False)
47 def test_unsigned(self
):
49 self
.assertIsInstance(s1
, Shape
)
50 self
.assertEqual(s1
.width
, 2)
51 self
.assertEqual(s1
.signed
, False)
53 def test_signed(self
):
55 self
.assertIsInstance(s1
, Shape
)
56 self
.assertEqual(s1
.width
, 2)
57 self
.assertEqual(s1
.signed
, True)
59 def test_cast_shape(self
):
60 s1
= Shape
.cast(unsigned(1))
61 self
.assertEqual(s1
.width
, 1)
62 self
.assertEqual(s1
.signed
, False)
63 s2
= Shape
.cast(signed(3))
64 self
.assertEqual(s2
.width
, 3)
65 self
.assertEqual(s2
.signed
, True)
67 def test_cast_int(self
):
69 self
.assertEqual(s1
.width
, 2)
70 self
.assertEqual(s1
.signed
, False)
72 def test_cast_int_wrong(self
):
73 with self
.assertRaises(TypeError,
74 msg
="Width must be a non-negative integer, not -1"):
77 def test_cast_tuple(self
):
78 with warnings
.catch_warnings():
79 warnings
.filterwarnings(action
="ignore", category
=DeprecationWarning)
80 s1
= Shape
.cast((1, True))
81 self
.assertEqual(s1
.width
, 1)
82 self
.assertEqual(s1
.signed
, True)
84 def test_cast_tuple_wrong(self
):
85 with warnings
.catch_warnings():
86 warnings
.filterwarnings(action
="ignore", category
=DeprecationWarning)
87 with self
.assertRaises(TypeError,
88 msg
="Width must be a non-negative integer, not -1"):
89 Shape
.cast((-1, True))
91 def test_cast_range(self
):
92 s1
= Shape
.cast(range(0, 8))
93 self
.assertEqual(s1
.width
, 3)
94 self
.assertEqual(s1
.signed
, False)
95 s2
= Shape
.cast(range(0, 9))
96 self
.assertEqual(s2
.width
, 4)
97 self
.assertEqual(s2
.signed
, False)
98 s3
= Shape
.cast(range(-7, 8))
99 self
.assertEqual(s3
.width
, 4)
100 self
.assertEqual(s3
.signed
, True)
101 s4
= Shape
.cast(range(0, 1))
102 self
.assertEqual(s4
.width
, 1)
103 self
.assertEqual(s4
.signed
, False)
104 s5
= Shape
.cast(range(-1, 0))
105 self
.assertEqual(s5
.width
, 1)
106 self
.assertEqual(s5
.signed
, True)
107 s6
= Shape
.cast(range(0, 0))
108 self
.assertEqual(s6
.width
, 0)
109 self
.assertEqual(s6
.signed
, False)
110 s7
= Shape
.cast(range(-1, -1))
111 self
.assertEqual(s7
.width
, 0)
112 self
.assertEqual(s7
.signed
, True)
114 def test_cast_enum(self
):
115 s1
= Shape
.cast(UnsignedEnum
)
116 self
.assertEqual(s1
.width
, 2)
117 self
.assertEqual(s1
.signed
, False)
118 s2
= Shape
.cast(SignedEnum
)
119 self
.assertEqual(s2
.width
, 2)
120 self
.assertEqual(s2
.signed
, True)
122 def test_cast_enum_bad(self
):
123 with self
.assertRaises(TypeError,
124 msg
="Only enumerations with integer values can be used as value shapes"):
125 Shape
.cast(StringEnum
)
127 def test_cast_bad(self
):
128 with self
.assertRaises(TypeError,
129 msg
="Object 'foo' cannot be used as value shape"):
133 class ValueTestCase(FHDLTestCase
):
135 self
.assertIsInstance(Value
.cast(0), Const
)
136 self
.assertIsInstance(Value
.cast(True), Const
)
138 self
.assertIs(Value
.cast(c
), c
)
139 with self
.assertRaises(TypeError,
140 msg
="Object 'str' cannot be converted to an nMigen value"):
143 def test_cast_enum(self
):
144 e1
= Value
.cast(UnsignedEnum
.FOO
)
145 self
.assertIsInstance(e1
, Const
)
146 self
.assertEqual(e1
.shape(), unsigned(2))
147 e2
= Value
.cast(SignedEnum
.FOO
)
148 self
.assertIsInstance(e2
, Const
)
149 self
.assertEqual(e2
.shape(), signed(2))
151 def test_cast_enum_wrong(self
):
152 with self
.assertRaises(TypeError,
153 msg
="Only enumerations with integer values can be used as value shapes"):
154 Value
.cast(StringEnum
.FOO
)
157 with self
.assertRaises(TypeError,
158 msg
="Attempted to convert nMigen value to boolean"):
163 self
.assertEqual(len(Const(10)), 4)
165 def test_getitem_int(self
):
167 self
.assertIsInstance(s1
, Slice
)
168 self
.assertEqual(s1
.start
, 0)
169 self
.assertEqual(s1
.stop
, 1)
171 self
.assertIsInstance(s2
, Slice
)
172 self
.assertEqual(s2
.start
, 3)
173 self
.assertEqual(s2
.stop
, 4)
174 with self
.assertRaises(IndexError,
175 msg
="Cannot index 5 bits into 4-bit value"):
178 def test_getitem_slice(self
):
180 self
.assertIsInstance(s1
, Slice
)
181 self
.assertEqual(s1
.start
, 1)
182 self
.assertEqual(s1
.stop
, 3)
184 self
.assertIsInstance(s2
, Slice
)
185 self
.assertEqual(s2
.start
, 1)
186 self
.assertEqual(s2
.stop
, 2)
188 self
.assertIsInstance(s3
, Cat
)
189 self
.assertIsInstance(s3
.parts
[0], Slice
)
190 self
.assertEqual(s3
.parts
[0].start
, 0)
191 self
.assertEqual(s3
.parts
[0].stop
, 1)
192 self
.assertIsInstance(s3
.parts
[1], Slice
)
193 self
.assertEqual(s3
.parts
[1].start
, 2)
194 self
.assertEqual(s3
.parts
[1].stop
, 3)
195 self
.assertIsInstance(s3
.parts
[2], Slice
)
196 self
.assertEqual(s3
.parts
[2].start
, 4)
197 self
.assertEqual(s3
.parts
[2].stop
, 5)
199 def test_getitem_wrong(self
):
200 with self
.assertRaises(TypeError,
201 msg
="Cannot index value with 'str'"):
205 class ConstTestCase(FHDLTestCase
):
206 def test_shape(self
):
207 self
.assertEqual(Const(0).shape(), unsigned(1))
208 self
.assertIsInstance(Const(0).shape(), Shape
)
209 self
.assertEqual(Const(1).shape(), unsigned(1))
210 self
.assertEqual(Const(10).shape(), unsigned(4))
211 self
.assertEqual(Const(-10).shape(), signed(5))
213 self
.assertEqual(Const(1, 4).shape(), unsigned(4))
214 self
.assertEqual(Const(-1, 4).shape(), signed(4))
215 self
.assertEqual(Const(1, signed(4)).shape(), signed(4))
216 self
.assertEqual(Const(0, unsigned(0)).shape(), unsigned(0))
218 def test_shape_wrong(self
):
219 with self
.assertRaises(TypeError,
220 msg
="Width must be a non-negative integer, not -1"):
223 def test_normalization(self
):
224 self
.assertEqual(Const(0b10110, signed(5)).value
, -10)
226 def test_value(self
):
227 self
.assertEqual(Const(10).value
, 10)
230 self
.assertEqual(repr(Const(10)), "(const 4'd10)")
231 self
.assertEqual(repr(Const(-10)), "(const 5'sd-10)")
234 with self
.assertRaises(TypeError):
238 class OperatorTestCase(FHDLTestCase
):
240 v
= Const(0, 4).bool()
241 self
.assertEqual(repr(v
), "(b (const 4'd0))")
242 self
.assertEqual(v
.shape(), unsigned(1))
244 def test_invert(self
):
246 self
.assertEqual(repr(v
), "(~ (const 4'd0))")
247 self
.assertEqual(v
.shape(), unsigned(4))
250 v1
= -Const(0, unsigned(4))
251 self
.assertEqual(repr(v1
), "(- (const 4'd0))")
252 self
.assertEqual(v1
.shape(), signed(5))
253 v2
= -Const(0, signed(4))
254 self
.assertEqual(repr(v2
), "(- (const 4'sd0))")
255 self
.assertEqual(v2
.shape(), signed(5))
258 v1
= Const(0, unsigned(4)) + Const(0, unsigned(6))
259 self
.assertEqual(repr(v1
), "(+ (const 4'd0) (const 6'd0))")
260 self
.assertEqual(v1
.shape(), unsigned(7))
261 v2
= Const(0, signed(4)) + Const(0, signed(6))
262 self
.assertEqual(v2
.shape(), signed(7))
263 v3
= Const(0, signed(4)) + Const(0, unsigned(4))
264 self
.assertEqual(v3
.shape(), signed(6))
265 v4
= Const(0, unsigned(4)) + Const(0, signed(4))
266 self
.assertEqual(v4
.shape(), signed(6))
267 v5
= 10 + Const(0, 4)
268 self
.assertEqual(v5
.shape(), unsigned(5))
271 v1
= Const(0, unsigned(4)) - Const(0, unsigned(6))
272 self
.assertEqual(repr(v1
), "(- (const 4'd0) (const 6'd0))")
273 self
.assertEqual(v1
.shape(), unsigned(7))
274 v2
= Const(0, signed(4)) - Const(0, signed(6))
275 self
.assertEqual(v2
.shape(), signed(7))
276 v3
= Const(0, signed(4)) - Const(0, unsigned(4))
277 self
.assertEqual(v3
.shape(), signed(6))
278 v4
= Const(0, unsigned(4)) - Const(0, signed(4))
279 self
.assertEqual(v4
.shape(), signed(6))
280 v5
= 10 - Const(0, 4)
281 self
.assertEqual(v5
.shape(), unsigned(5))
284 v1
= Const(0, unsigned(4)) * Const(0, unsigned(6))
285 self
.assertEqual(repr(v1
), "(* (const 4'd0) (const 6'd0))")
286 self
.assertEqual(v1
.shape(), unsigned(10))
287 v2
= Const(0, signed(4)) * Const(0, signed(6))
288 self
.assertEqual(v2
.shape(), signed(10))
289 v3
= Const(0, signed(4)) * Const(0, unsigned(4))
290 self
.assertEqual(v3
.shape(), signed(8))
291 v5
= 10 * Const(0, 4)
292 self
.assertEqual(v5
.shape(), unsigned(8))
295 v1
= Const(0, unsigned(4)) % Const(0, unsigned(6))
296 self
.assertEqual(repr(v1
), "(% (const 4'd0) (const 6'd0))")
297 self
.assertEqual(v1
.shape(), unsigned(4))
298 v3
= Const(0, signed(4)) % Const(0, unsigned(4))
299 self
.assertEqual(v3
.shape(), signed(4))
300 v5
= 10 % Const(0, 4)
301 self
.assertEqual(v5
.shape(), unsigned(4))
303 def test_mod_wrong(self
):
304 with self
.assertRaises(NotImplementedError,
305 msg
="Division by a signed value is not supported"):
306 Const(0, signed(4)) % Const(0, signed(6))
308 def test_floordiv(self
):
309 v1
= Const(0, unsigned(4)) // Const(0, unsigned(6))
310 self
.assertEqual(repr(v1
), "(// (const 4'd0) (const 6'd0))")
311 self
.assertEqual(v1
.shape(), unsigned(4))
312 v3
= Const(0, signed(4)) // Const(0, unsigned(4))
313 self
.assertEqual(v3
.shape(), signed(4))
314 v5
= 10 // Const(0, 4)
315 self
.assertEqual(v5
.shape(), unsigned(4))
317 def test_floordiv_wrong(self
):
318 with self
.assertRaises(NotImplementedError,
319 msg
="Division by a signed value is not supported"):
320 Const(0, signed(4)) // Const(0, signed(6))
323 v1
= Const(0, unsigned(4)) & Const(0, unsigned(6))
324 self
.assertEqual(repr(v1
), "(& (const 4'd0) (const 6'd0))")
325 self
.assertEqual(v1
.shape(), unsigned(6))
326 v2
= Const(0, signed(4)) & Const(0, signed(6))
327 self
.assertEqual(v2
.shape(), signed(6))
328 v3
= Const(0, signed(4)) & Const(0, unsigned(4))
329 self
.assertEqual(v3
.shape(), signed(5))
330 v4
= Const(0, unsigned(4)) & Const(0, signed(4))
331 self
.assertEqual(v4
.shape(), signed(5))
332 v5
= 10 & Const(0, 4)
333 self
.assertEqual(v5
.shape(), unsigned(4))
336 v1
= Const(0, unsigned(4)) |
Const(0, unsigned(6))
337 self
.assertEqual(repr(v1
), "(| (const 4'd0) (const 6'd0))")
338 self
.assertEqual(v1
.shape(), unsigned(6))
339 v2
= Const(0, signed(4)) |
Const(0, signed(6))
340 self
.assertEqual(v2
.shape(), signed(6))
341 v3
= Const(0, signed(4)) |
Const(0, unsigned(4))
342 self
.assertEqual(v3
.shape(), signed(5))
343 v4
= Const(0, unsigned(4)) |
Const(0, signed(4))
344 self
.assertEqual(v4
.shape(), signed(5))
345 v5
= 10 |
Const(0, 4)
346 self
.assertEqual(v5
.shape(), unsigned(4))
349 v1
= Const(0, unsigned(4)) ^
Const(0, unsigned(6))
350 self
.assertEqual(repr(v1
), "(^ (const 4'd0) (const 6'd0))")
351 self
.assertEqual(v1
.shape(), unsigned(6))
352 v2
= Const(0, signed(4)) ^
Const(0, signed(6))
353 self
.assertEqual(v2
.shape(), signed(6))
354 v3
= Const(0, signed(4)) ^
Const(0, unsigned(4))
355 self
.assertEqual(v3
.shape(), signed(5))
356 v4
= Const(0, unsigned(4)) ^
Const(0, signed(4))
357 self
.assertEqual(v4
.shape(), signed(5))
358 v5
= 10 ^
Const(0, 4)
359 self
.assertEqual(v5
.shape(), unsigned(4))
362 v1
= Const(1, 4) << Const(4)
363 self
.assertEqual(repr(v1
), "(<< (const 4'd1) (const 3'd4))")
364 self
.assertEqual(v1
.shape(), unsigned(11))
366 def test_shl_wrong(self
):
367 with self
.assertRaises(NotImplementedError,
368 msg
="Shift by a signed value is not supported"):
369 1 << Const(0, signed(6))
370 with self
.assertRaises(NotImplementedError,
371 msg
="Shift by a signed value is not supported"):
372 Const(1, unsigned(4)) << -1
375 v1
= Const(1, 4) >> Const(4)
376 self
.assertEqual(repr(v1
), "(>> (const 4'd1) (const 3'd4))")
377 self
.assertEqual(v1
.shape(), unsigned(4))
379 def test_shr_wrong(self
):
380 with self
.assertRaises(NotImplementedError,
381 msg
="Shift by a signed value is not supported"):
382 1 << Const(0, signed(6))
383 with self
.assertRaises(NotImplementedError,
384 msg
="Shift by a signed value is not supported"):
385 Const(1, unsigned(4)) << -1
388 v
= Const(0, 4) < Const(0, 6)
389 self
.assertEqual(repr(v
), "(< (const 4'd0) (const 6'd0))")
390 self
.assertEqual(v
.shape(), unsigned(1))
393 v
= Const(0, 4) <= Const(0, 6)
394 self
.assertEqual(repr(v
), "(<= (const 4'd0) (const 6'd0))")
395 self
.assertEqual(v
.shape(), unsigned(1))
398 v
= Const(0, 4) > Const(0, 6)
399 self
.assertEqual(repr(v
), "(> (const 4'd0) (const 6'd0))")
400 self
.assertEqual(v
.shape(), unsigned(1))
403 v
= Const(0, 4) >= Const(0, 6)
404 self
.assertEqual(repr(v
), "(>= (const 4'd0) (const 6'd0))")
405 self
.assertEqual(v
.shape(), unsigned(1))
408 v
= Const(0, 4) == Const(0, 6)
409 self
.assertEqual(repr(v
), "(== (const 4'd0) (const 6'd0))")
410 self
.assertEqual(v
.shape(), unsigned(1))
413 v
= Const(0, 4) != Const(0, 6)
414 self
.assertEqual(repr(v
), "(!= (const 4'd0) (const 6'd0))")
415 self
.assertEqual(v
.shape(), unsigned(1))
419 v1
= Mux(s
, Const(0, unsigned(4)), Const(0, unsigned(6)))
420 self
.assertEqual(repr(v1
), "(m (const 1'd0) (const 4'd0) (const 6'd0))")
421 self
.assertEqual(v1
.shape(), unsigned(6))
422 v2
= Mux(s
, Const(0, signed(4)), Const(0, signed(6)))
423 self
.assertEqual(v2
.shape(), signed(6))
424 v3
= Mux(s
, Const(0, signed(4)), Const(0, unsigned(4)))
425 self
.assertEqual(v3
.shape(), signed(5))
426 v4
= Mux(s
, Const(0, unsigned(4)), Const(0, signed(4)))
427 self
.assertEqual(v4
.shape(), signed(5))
429 def test_mux_wide(self
):
431 v
= Mux(s
, Const(0, unsigned(4)), Const(0, unsigned(6)))
432 self
.assertEqual(repr(v
), "(m (b (const 3'd4)) (const 4'd0) (const 6'd0))")
434 def test_mux_bool(self
):
435 v
= Mux(True, Const(0), Const(0))
436 self
.assertEqual(repr(v
), "(m (const 1'd1) (const 1'd0) (const 1'd0))")
440 self
.assertEqual(repr(v
), "(b (const 1'd0))")
441 self
.assertEqual(v
.shape(), unsigned(1))
444 v
= Const(0b101).any()
445 self
.assertEqual(repr(v
), "(r| (const 3'd5))")
448 v
= Const(0b101).all()
449 self
.assertEqual(repr(v
), "(r& (const 3'd5))")
452 v
= Const(0b101).xor()
453 self
.assertEqual(repr(v
), "(r^ (const 3'd5))")
455 def test_matches(self
):
457 self
.assertRepr(s
.matches(), "(const 1'd0)")
458 self
.assertRepr(s
.matches(1), """
459 (== (sig s) (const 1'd1))
461 self
.assertRepr(s
.matches(0, 1), """
462 (r| (cat (== (sig s) (const 1'd0)) (== (sig s) (const 1'd1))))
464 self
.assertRepr(s
.matches("10--"), """
465 (== (& (sig s) (const 4'd12)) (const 4'd8))
468 def test_matches_enum(self
):
469 s
= Signal(SignedEnum
)
470 self
.assertRepr(s
.matches(SignedEnum
.FOO
), """
471 (== (sig s) (const 1'sd-1))
474 def test_matches_width_wrong(self
):
476 with self
.assertRaises(SyntaxError,
477 msg
="Match pattern '--' must have the same width as match value (which is 4)"):
479 with self
.assertWarns(SyntaxWarning,
480 msg
="Match pattern '10110' is wider than match value (which has width 4); "
481 "comparison will never be true"):
484 def test_matches_bits_wrong(self
):
486 with self
.assertRaises(SyntaxError,
487 msg
="Match pattern 'abc' must consist of 0, 1, and - (don't care) bits"):
490 def test_matches_pattern_wrong(self
):
492 with self
.assertRaises(SyntaxError,
493 msg
="Match pattern must be an integer, a string, or an enumeration, not 1.0"):
497 with self
.assertRaises(TypeError):
498 hash(Const(0) + Const(0))
501 class SliceTestCase(FHDLTestCase
):
502 def test_shape(self
):
504 self
.assertEqual(s1
.shape(), unsigned(1))
505 self
.assertIsInstance(s1
.shape(), Shape
)
507 self
.assertEqual(s2
.shape(), unsigned(2))
509 def test_start_end_negative(self
):
512 self
.assertEqual((s1
.start
, s1
.stop
), (0, 7))
513 s1
= Slice(c
, -4, -1)
514 self
.assertEqual((s1
.start
, s1
.stop
), (4, 7))
516 def test_start_end_wrong(self
):
517 with self
.assertRaises(TypeError,
518 msg
="Slice start must be an integer, not 'x'"):
520 with self
.assertRaises(TypeError,
521 msg
="Slice stop must be an integer, not 'x'"):
524 def test_start_end_out_of_range(self
):
526 with self
.assertRaises(IndexError,
527 msg
="Cannot start slice 10 bits into 8-bit value"):
529 with self
.assertRaises(IndexError,
530 msg
="Cannot stop slice 12 bits into 8-bit value"):
532 with self
.assertRaises(IndexError,
533 msg
="Slice start 4 must be less than slice stop 2"):
538 self
.assertEqual(repr(s1
), "(slice (const 4'd10) 2:3)")
541 class BitSelectTestCase(FHDLTestCase
):
544 self
.s
= Signal(range(self
.c
.width
))
546 def test_shape(self
):
547 s1
= self
.c
.bit_select(self
.s
, 2)
548 self
.assertIsInstance(s1
, Part
)
549 self
.assertEqual(s1
.shape(), unsigned(2))
550 self
.assertIsInstance(s1
.shape(), Shape
)
551 s2
= self
.c
.bit_select(self
.s
, 0)
552 self
.assertIsInstance(s2
, Part
)
553 self
.assertEqual(s2
.shape(), unsigned(0))
555 def test_stride(self
):
556 s1
= self
.c
.bit_select(self
.s
, 2)
557 self
.assertIsInstance(s1
, Part
)
558 self
.assertEqual(s1
.stride
, 1)
560 def test_const(self
):
561 s1
= self
.c
.bit_select(1, 2)
562 self
.assertIsInstance(s1
, Slice
)
563 self
.assertRepr(s1
, """(slice (const 8'd0) 1:3)""")
565 def test_width_wrong(self
):
566 with self
.assertRaises(TypeError):
567 self
.c
.bit_select(self
.s
, -1)
570 s
= self
.c
.bit_select(self
.s
, 2)
571 self
.assertEqual(repr(s
), "(part (const 8'd0) (sig s) 2 1)")
574 class WordSelectTestCase(FHDLTestCase
):
577 self
.s
= Signal(range(self
.c
.width
))
579 def test_shape(self
):
580 s1
= self
.c
.word_select(self
.s
, 2)
581 self
.assertIsInstance(s1
, Part
)
582 self
.assertEqual(s1
.shape(), unsigned(2))
583 self
.assertIsInstance(s1
.shape(), Shape
)
585 def test_stride(self
):
586 s1
= self
.c
.word_select(self
.s
, 2)
587 self
.assertIsInstance(s1
, Part
)
588 self
.assertEqual(s1
.stride
, 2)
590 def test_const(self
):
591 s1
= self
.c
.word_select(1, 2)
592 self
.assertIsInstance(s1
, Slice
)
593 self
.assertRepr(s1
, """(slice (const 8'd0) 2:4)""")
595 def test_width_wrong(self
):
596 with self
.assertRaises(TypeError):
597 self
.c
.word_select(self
.s
, 0)
598 with self
.assertRaises(TypeError):
599 self
.c
.word_select(self
.s
, -1)
602 s
= self
.c
.word_select(self
.s
, 2)
603 self
.assertEqual(repr(s
), "(part (const 8'd0) (sig s) 2 2)")
606 class CatTestCase(FHDLTestCase
):
607 def test_shape(self
):
609 self
.assertEqual(c0
.shape(), unsigned(0))
610 self
.assertIsInstance(c0
.shape(), Shape
)
612 self
.assertEqual(c1
.shape(), unsigned(4))
613 c2
= Cat(Const(10), Const(1))
614 self
.assertEqual(c2
.shape(), unsigned(5))
615 c3
= Cat(Const(10), Const(1), Const(0))
616 self
.assertEqual(c3
.shape(), unsigned(6))
619 c1
= Cat(Const(10), Const(1))
620 self
.assertEqual(repr(c1
), "(cat (const 4'd10) (const 1'd1))")
623 class ReplTestCase(FHDLTestCase
):
624 def test_shape(self
):
625 s1
= Repl(Const(10), 3)
626 self
.assertEqual(s1
.shape(), unsigned(12))
627 self
.assertIsInstance(s1
.shape(), Shape
)
628 s2
= Repl(Const(10), 0)
629 self
.assertEqual(s2
.shape(), unsigned(0))
631 def test_count_wrong(self
):
632 with self
.assertRaises(TypeError):
634 with self
.assertRaises(TypeError):
635 Repl(Const(10), "str")
638 s
= Repl(Const(10), 3)
639 self
.assertEqual(repr(s
), "(repl (const 4'd10) 3)")
642 class ArrayTestCase(FHDLTestCase
):
643 def test_acts_like_array(self
):
645 self
.assertSequenceEqual(a
, [1,2,3])
646 self
.assertEqual(a
[1], 2)
648 self
.assertSequenceEqual(a
, [1,4,3])
650 self
.assertSequenceEqual(a
, [1,3])
652 self
.assertSequenceEqual(a
, [1,2,3])
654 def test_becomes_immutable(self
):
656 s1
= Signal(range(len(a
)))
657 s2
= Signal(range(len(a
)))
660 with self
.assertRaisesRegex(ValueError,
661 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
663 with self
.assertRaisesRegex(ValueError,
664 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
666 with self
.assertRaisesRegex(ValueError,
667 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
672 self
.assertEqual(repr(a
), "(array mutable [1, 2, 3])")
673 s
= Signal(range(len(a
)))
675 self
.assertEqual(repr(a
), "(array [1, 2, 3])")
678 class ArrayProxyTestCase(FHDLTestCase
):
679 def test_index_shape(self
):
680 m
= Array(Array(x
* y
for y
in range(1, 4)) for x
in range(1, 4))
684 self
.assertEqual(v
.shape(), unsigned(4))
686 def test_attr_shape(self
):
687 from collections
import namedtuple
688 pair
= namedtuple("pair", ("p", "n"))
689 a
= Array(pair(i
, -i
) for i
in range(10))
690 s
= Signal(range(len(a
)))
692 self
.assertEqual(v
.p
.shape(), unsigned(4))
693 self
.assertEqual(v
.n
.shape(), signed(6))
699 self
.assertEqual(repr(v
), "(proxy (array [1, 2, 3]) (sig s))")
702 class SignalTestCase(FHDLTestCase
):
703 def test_shape(self
):
705 self
.assertEqual(s1
.shape(), unsigned(1))
706 self
.assertIsInstance(s1
.shape(), Shape
)
708 self
.assertEqual(s2
.shape(), unsigned(2))
709 s3
= Signal(unsigned(2))
710 self
.assertEqual(s3
.shape(), unsigned(2))
711 s4
= Signal(signed(2))
712 self
.assertEqual(s4
.shape(), signed(2))
714 self
.assertEqual(s5
.shape(), unsigned(0))
715 s6
= Signal(range(16))
716 self
.assertEqual(s6
.shape(), unsigned(4))
717 s7
= Signal(range(4, 16))
718 self
.assertEqual(s7
.shape(), unsigned(4))
719 s8
= Signal(range(-4, 16))
720 self
.assertEqual(s8
.shape(), signed(5))
721 s9
= Signal(range(-20, 16))
722 self
.assertEqual(s9
.shape(), signed(6))
723 s10
= Signal(range(0))
724 self
.assertEqual(s10
.shape(), unsigned(0))
725 s11
= Signal(range(1))
726 self
.assertEqual(s11
.shape(), unsigned(1))
728 def test_shape_wrong(self
):
729 with self
.assertRaises(TypeError,
730 msg
="Width must be a non-negative integer, not -10"):
735 self
.assertEqual(s1
.name
, "s1")
736 s2
= Signal(name
="sig")
737 self
.assertEqual(s2
.name
, "sig")
739 def test_reset(self
):
740 s1
= Signal(4, reset
=0b111, reset_less
=True)
741 self
.assertEqual(s1
.reset
, 0b111)
742 self
.assertEqual(s1
.reset_less
, True)
744 def test_reset_enum(self
):
745 s1
= Signal(2, reset
=UnsignedEnum
.BAR
)
746 self
.assertEqual(s1
.reset
, 2)
747 with self
.assertRaises(TypeError,
748 msg
="Reset value has to be an int or an integral Enum"
750 Signal(1, reset
=StringEnum
.FOO
)
752 def test_reset_narrow(self
):
753 with self
.assertWarns(SyntaxWarning,
754 msg
="Reset value 8 requires 4 bits to represent, but the signal only has 3 bits"):
756 with self
.assertWarns(SyntaxWarning,
757 msg
="Reset value 4 requires 4 bits to represent, but the signal only has 3 bits"):
758 Signal(signed(3), reset
=4)
759 with self
.assertWarns(SyntaxWarning,
760 msg
="Reset value -5 requires 4 bits to represent, but the signal only has 3 bits"):
761 Signal(signed(3), reset
=-5)
763 def test_attrs(self
):
765 self
.assertEqual(s1
.attrs
, {})
766 s2
= Signal(attrs
={"no_retiming": True})
767 self
.assertEqual(s2
.attrs
, {"no_retiming": True})
771 self
.assertEqual(repr(s1
), "(sig s1)")
774 s1
= Signal
.like(Signal(4))
775 self
.assertEqual(s1
.shape(), unsigned(4))
776 s2
= Signal
.like(Signal(range(-15, 1)))
777 self
.assertEqual(s2
.shape(), signed(5))
778 s3
= Signal
.like(Signal(4, reset
=0b111, reset_less
=True))
779 self
.assertEqual(s3
.reset
, 0b111)
780 self
.assertEqual(s3
.reset_less
, True)
781 s4
= Signal
.like(Signal(attrs
={"no_retiming": True}))
782 self
.assertEqual(s4
.attrs
, {"no_retiming": True})
783 s5
= Signal
.like(Signal(decoder
=str))
784 self
.assertEqual(s5
.decoder
, str)
786 self
.assertEqual(s6
.shape(), unsigned(4))
787 s7
= [Signal
.like(Signal(4))][0]
788 self
.assertEqual(s7
.name
, "$like")
789 s8
= Signal
.like(s1
, name_suffix
="_ff")
790 self
.assertEqual(s8
.name
, "s1_ff")
792 def test_decoder(self
):
796 s
= Signal(decoder
=Color
)
797 self
.assertEqual(s
.decoder(1), "RED/1")
798 self
.assertEqual(s
.decoder(3), "3")
801 s1
= Signal(UnsignedEnum
)
802 self
.assertEqual(s1
.shape(), unsigned(2))
803 s2
= Signal(SignedEnum
)
804 self
.assertEqual(s2
.shape(), signed(2))
805 self
.assertEqual(s2
.decoder(SignedEnum
.FOO
), "FOO/-1")
808 class ClockSignalTestCase(FHDLTestCase
):
809 def test_domain(self
):
811 self
.assertEqual(s1
.domain
, "sync")
812 s2
= ClockSignal("pix")
813 self
.assertEqual(s2
.domain
, "pix")
815 with self
.assertRaises(TypeError,
816 msg
="Clock domain name must be a string, not 1"):
819 def test_shape(self
):
821 self
.assertEqual(s1
.shape(), unsigned(1))
822 self
.assertIsInstance(s1
.shape(), Shape
)
826 self
.assertEqual(repr(s1
), "(clk sync)")
828 def test_wrong_name_comb(self
):
829 with self
.assertRaises(ValueError,
830 msg
="Domain 'comb' does not have a clock"):
834 class ResetSignalTestCase(FHDLTestCase
):
835 def test_domain(self
):
837 self
.assertEqual(s1
.domain
, "sync")
838 s2
= ResetSignal("pix")
839 self
.assertEqual(s2
.domain
, "pix")
841 with self
.assertRaises(TypeError,
842 msg
="Clock domain name must be a string, not 1"):
845 def test_shape(self
):
847 self
.assertEqual(s1
.shape(), unsigned(1))
848 self
.assertIsInstance(s1
.shape(), Shape
)
852 self
.assertEqual(repr(s1
), "(rst sync)")
854 def test_wrong_name_comb(self
):
855 with self
.assertRaises(ValueError,
856 msg
="Domain 'comb' does not have a reset"):
860 class MockUserValue(UserValue
):
861 def __init__(self
, lowered
):
864 self
.lowered
= lowered
867 self
.lower_count
+= 1
871 class UserValueTestCase(FHDLTestCase
):
872 def test_shape(self
):
873 uv
= MockUserValue(1)
874 self
.assertEqual(uv
.shape(), unsigned(1))
875 self
.assertIsInstance(uv
.shape(), Shape
)
877 self
.assertEqual(uv
.shape(), unsigned(1))
878 self
.assertEqual(uv
.lower_count
, 1)
881 class SampleTestCase(FHDLTestCase
):
882 def test_const(self
):
883 s
= Sample(1, 1, "sync")
884 self
.assertEqual(s
.shape(), unsigned(1))
886 def test_signal(self
):
887 s1
= Sample(Signal(2), 1, "sync")
888 self
.assertEqual(s1
.shape(), unsigned(2))
889 s2
= Sample(ClockSignal(), 1, "sync")
890 s3
= Sample(ResetSignal(), 1, "sync")
892 def test_wrong_value_operator(self
):
893 with self
.assertRaises(TypeError,
894 "Sampled value must be a signal or a constant, not "
895 "(+ (sig $signal) (const 1'd1))"):
896 Sample(Signal() + 1, 1, "sync")
898 def test_wrong_clocks_neg(self
):
899 with self
.assertRaises(ValueError,
900 "Cannot sample a value 1 cycles in the future"):
901 Sample(Signal(), -1, "sync")
903 def test_wrong_domain(self
):
904 with self
.assertRaises(TypeError,
905 "Domain name must be a string or None, not 0"):
906 Sample(Signal(), 1, 0)
909 class InitialTestCase(FHDLTestCase
):
910 def test_initial(self
):
912 self
.assertEqual(i
.shape(), unsigned(1))