3 from ..hdl
.ast
import *
7 class ValueTestCase(FHDLTestCase
):
9 self
.assertIsInstance(Value
.wrap(0), Const
)
10 self
.assertIsInstance(Value
.wrap(True), Const
)
12 self
.assertIs(Value
.wrap(c
), c
)
13 with self
.assertRaises(TypeError,
14 msg
="Object ''str'' is not an nMigen value"):
18 with self
.assertRaises(TypeError,
19 msg
="Attempted to convert nMigen value to boolean"):
24 self
.assertEqual(len(Const(10)), 4)
26 def test_getitem_int(self
):
28 self
.assertIsInstance(s1
, Slice
)
29 self
.assertEqual(s1
.start
, 0)
30 self
.assertEqual(s1
.end
, 1)
32 self
.assertIsInstance(s2
, Slice
)
33 self
.assertEqual(s2
.start
, 3)
34 self
.assertEqual(s2
.end
, 4)
35 with self
.assertRaises(IndexError,
36 msg
="Cannot index 5 bits into 4-bit value"):
39 def test_getitem_slice(self
):
41 self
.assertIsInstance(s1
, Slice
)
42 self
.assertEqual(s1
.start
, 1)
43 self
.assertEqual(s1
.end
, 3)
45 self
.assertIsInstance(s2
, Slice
)
46 self
.assertEqual(s2
.start
, 1)
47 self
.assertEqual(s2
.end
, 2)
49 self
.assertIsInstance(s3
, Cat
)
50 self
.assertIsInstance(s3
.parts
[0], Slice
)
51 self
.assertEqual(s3
.parts
[0].start
, 0)
52 self
.assertEqual(s3
.parts
[0].end
, 1)
53 self
.assertIsInstance(s3
.parts
[1], Slice
)
54 self
.assertEqual(s3
.parts
[1].start
, 2)
55 self
.assertEqual(s3
.parts
[1].end
, 3)
56 self
.assertIsInstance(s3
.parts
[2], Slice
)
57 self
.assertEqual(s3
.parts
[2].start
, 4)
58 self
.assertEqual(s3
.parts
[2].end
, 5)
60 def test_getitem_wrong(self
):
61 with self
.assertRaises(TypeError,
62 msg
="Cannot index value with 'str'"):
66 class ConstTestCase(FHDLTestCase
):
68 self
.assertEqual(Const(0).shape(), (1, False))
69 self
.assertEqual(Const(1).shape(), (1, False))
70 self
.assertEqual(Const(10).shape(), (4, False))
71 self
.assertEqual(Const(-10).shape(), (5, True))
73 self
.assertEqual(Const(1, 4).shape(), (4, False))
74 self
.assertEqual(Const(1, (4, True)).shape(), (4, True))
75 self
.assertEqual(Const(0, (0, False)).shape(), (0, False))
77 def test_shape_bad(self
):
78 with self
.assertRaises(TypeError,
79 msg
="Width must be a non-negative integer, not '-1'"):
82 def test_normalization(self
):
83 self
.assertEqual(Const(0b10110, (5, True)).value
, -10)
86 self
.assertEqual(Const(10).value
, 10)
89 self
.assertEqual(repr(Const(10)), "(const 4'd10)")
90 self
.assertEqual(repr(Const(-10)), "(const 5'sd-10)")
93 with self
.assertRaises(TypeError):
97 class OperatorTestCase(FHDLTestCase
):
99 v
= Const(0, 4).bool()
100 self
.assertEqual(repr(v
), "(b (const 4'd0))")
101 self
.assertEqual(v
.shape(), (1, False))
103 def test_invert(self
):
105 self
.assertEqual(repr(v
), "(~ (const 4'd0))")
106 self
.assertEqual(v
.shape(), (4, False))
109 v1
= -Const(0, (4, False))
110 self
.assertEqual(repr(v1
), "(- (const 4'd0))")
111 self
.assertEqual(v1
.shape(), (5, True))
112 v2
= -Const(0, (4, True))
113 self
.assertEqual(repr(v2
), "(- (const 4'sd0))")
114 self
.assertEqual(v2
.shape(), (4, True))
117 v1
= Const(0, (4, False)) + Const(0, (6, False))
118 self
.assertEqual(repr(v1
), "(+ (const 4'd0) (const 6'd0))")
119 self
.assertEqual(v1
.shape(), (7, False))
120 v2
= Const(0, (4, True)) + Const(0, (6, True))
121 self
.assertEqual(v2
.shape(), (7, True))
122 v3
= Const(0, (4, True)) + Const(0, (4, False))
123 self
.assertEqual(v3
.shape(), (6, True))
124 v4
= Const(0, (4, False)) + Const(0, (4, True))
125 self
.assertEqual(v4
.shape(), (6, True))
126 v5
= 10 + Const(0, 4)
127 self
.assertEqual(v5
.shape(), (5, False))
130 v1
= Const(0, (4, False)) - Const(0, (6, False))
131 self
.assertEqual(repr(v1
), "(- (const 4'd0) (const 6'd0))")
132 self
.assertEqual(v1
.shape(), (7, False))
133 v2
= Const(0, (4, True)) - Const(0, (6, True))
134 self
.assertEqual(v2
.shape(), (7, True))
135 v3
= Const(0, (4, True)) - Const(0, (4, False))
136 self
.assertEqual(v3
.shape(), (6, True))
137 v4
= Const(0, (4, False)) - Const(0, (4, True))
138 self
.assertEqual(v4
.shape(), (6, True))
139 v5
= 10 - Const(0, 4)
140 self
.assertEqual(v5
.shape(), (5, False))
143 v1
= Const(0, (4, False)) * Const(0, (6, False))
144 self
.assertEqual(repr(v1
), "(* (const 4'd0) (const 6'd0))")
145 self
.assertEqual(v1
.shape(), (10, False))
146 v2
= Const(0, (4, True)) * Const(0, (6, True))
147 self
.assertEqual(v2
.shape(), (10, True))
148 v3
= Const(0, (4, True)) * Const(0, (4, False))
149 self
.assertEqual(v3
.shape(), (8, True))
150 v5
= 10 * Const(0, 4)
151 self
.assertEqual(v5
.shape(), (8, False))
154 v1
= Const(0, (4, False)) & Const(0, (6, False))
155 self
.assertEqual(repr(v1
), "(& (const 4'd0) (const 6'd0))")
156 self
.assertEqual(v1
.shape(), (6, False))
157 v2
= Const(0, (4, True)) & Const(0, (6, True))
158 self
.assertEqual(v2
.shape(), (6, True))
159 v3
= Const(0, (4, True)) & Const(0, (4, False))
160 self
.assertEqual(v3
.shape(), (5, True))
161 v4
= Const(0, (4, False)) & Const(0, (4, True))
162 self
.assertEqual(v4
.shape(), (5, True))
163 v5
= 10 & Const(0, 4)
164 self
.assertEqual(v5
.shape(), (4, False))
167 v1
= Const(0, (4, False)) |
Const(0, (6, False))
168 self
.assertEqual(repr(v1
), "(| (const 4'd0) (const 6'd0))")
169 self
.assertEqual(v1
.shape(), (6, False))
170 v2
= Const(0, (4, True)) |
Const(0, (6, True))
171 self
.assertEqual(v2
.shape(), (6, True))
172 v3
= Const(0, (4, True)) |
Const(0, (4, False))
173 self
.assertEqual(v3
.shape(), (5, True))
174 v4
= Const(0, (4, False)) |
Const(0, (4, True))
175 self
.assertEqual(v4
.shape(), (5, True))
176 v5
= 10 |
Const(0, 4)
177 self
.assertEqual(v5
.shape(), (4, False))
180 v1
= Const(0, (4, False)) ^
Const(0, (6, False))
181 self
.assertEqual(repr(v1
), "(^ (const 4'd0) (const 6'd0))")
182 self
.assertEqual(v1
.shape(), (6, False))
183 v2
= Const(0, (4, True)) ^
Const(0, (6, True))
184 self
.assertEqual(v2
.shape(), (6, True))
185 v3
= Const(0, (4, True)) ^
Const(0, (4, False))
186 self
.assertEqual(v3
.shape(), (5, True))
187 v4
= Const(0, (4, False)) ^
Const(0, (4, True))
188 self
.assertEqual(v4
.shape(), (5, True))
189 v5
= 10 ^
Const(0, 4)
190 self
.assertEqual(v5
.shape(), (4, False))
193 v1
= Const(1, 4) << Const(4)
194 self
.assertEqual(repr(v1
), "(<< (const 4'd1) (const 3'd4))")
195 self
.assertEqual(v1
.shape(), (11, False))
196 v2
= Const(1, 4) << Const(-3)
197 self
.assertEqual(v2
.shape(), (7, False))
200 v1
= Const(1, 4) >> Const(4)
201 self
.assertEqual(repr(v1
), "(>> (const 4'd1) (const 3'd4))")
202 self
.assertEqual(v1
.shape(), (4, False))
203 v2
= Const(1, 4) >> Const(-3)
204 self
.assertEqual(v2
.shape(), (8, False))
207 v
= Const(0, 4) < Const(0, 6)
208 self
.assertEqual(repr(v
), "(< (const 4'd0) (const 6'd0))")
209 self
.assertEqual(v
.shape(), (1, False))
212 v
= Const(0, 4) <= Const(0, 6)
213 self
.assertEqual(repr(v
), "(<= (const 4'd0) (const 6'd0))")
214 self
.assertEqual(v
.shape(), (1, False))
217 v
= Const(0, 4) > Const(0, 6)
218 self
.assertEqual(repr(v
), "(> (const 4'd0) (const 6'd0))")
219 self
.assertEqual(v
.shape(), (1, False))
222 v
= Const(0, 4) >= Const(0, 6)
223 self
.assertEqual(repr(v
), "(>= (const 4'd0) (const 6'd0))")
224 self
.assertEqual(v
.shape(), (1, False))
227 v
= Const(0, 4) == Const(0, 6)
228 self
.assertEqual(repr(v
), "(== (const 4'd0) (const 6'd0))")
229 self
.assertEqual(v
.shape(), (1, False))
232 v
= Const(0, 4) != Const(0, 6)
233 self
.assertEqual(repr(v
), "(!= (const 4'd0) (const 6'd0))")
234 self
.assertEqual(v
.shape(), (1, False))
238 v1
= Mux(s
, Const(0, (4, False)), Const(0, (6, False)))
239 self
.assertEqual(repr(v1
), "(m (const 1'd0) (const 4'd0) (const 6'd0))")
240 self
.assertEqual(v1
.shape(), (6, False))
241 v2
= Mux(s
, Const(0, (4, True)), Const(0, (6, True)))
242 self
.assertEqual(v2
.shape(), (6, True))
243 v3
= Mux(s
, Const(0, (4, True)), Const(0, (4, False)))
244 self
.assertEqual(v3
.shape(), (5, True))
245 v4
= Mux(s
, Const(0, (4, False)), Const(0, (4, True)))
246 self
.assertEqual(v4
.shape(), (5, True))
250 self
.assertEqual(repr(v
), "(b (const 1'd0))")
251 self
.assertEqual(v
.shape(), (1, False))
254 with self
.assertRaises(TypeError):
255 hash(Const(0) + Const(0))
258 class SliceTestCase(FHDLTestCase
):
259 def test_shape(self
):
261 self
.assertEqual(s1
.shape(), (1, False))
263 self
.assertEqual(s2
.shape(), (2, False))
265 def test_start_end_negative(self
):
268 self
.assertEqual((s1
.start
, s1
.end
), (0, 7))
269 s1
= Slice(c
, -4, -1)
270 self
.assertEqual((s1
.start
, s1
.end
), (4, 7))
272 def test_start_end_wrong(self
):
273 with self
.assertRaises(TypeError,
274 msg
="Slice start must be an integer, not ''x''"):
276 with self
.assertRaises(TypeError,
277 msg
="Slice end must be an integer, not ''x''"):
280 def test_start_end_out_of_range(self
):
282 with self
.assertRaises(IndexError,
283 msg
="Cannot start slice 10 bits into 8-bit value"):
285 with self
.assertRaises(IndexError,
286 msg
="Cannot end slice 12 bits into 8-bit value"):
288 with self
.assertRaises(IndexError,
289 msg
="Slice start 4 must be less than slice end 2"):
294 self
.assertEqual(repr(s1
), "(slice (const 4'd10) 2:3)")
297 class BitSelectTestCase(FHDLTestCase
):
300 self
.s
= Signal(max=self
.c
.nbits
)
302 def test_shape(self
):
303 s1
= self
.c
.bit_select(self
.s
, 2)
304 self
.assertEqual(s1
.shape(), (2, False))
305 s2
= self
.c
.bit_select(self
.s
, 0)
306 self
.assertEqual(s2
.shape(), (0, False))
308 def test_stride(self
):
309 s1
= self
.c
.bit_select(self
.s
, 2)
310 self
.assertEqual(s1
.stride
, 1)
312 def test_width_bad(self
):
313 with self
.assertRaises(TypeError):
314 self
.c
.bit_select(self
.s
, -1)
317 s
= self
.c
.bit_select(self
.s
, 2)
318 self
.assertEqual(repr(s
), "(part (const 8'd0) (sig s) 2 1)")
321 class WordSelectTestCase(FHDLTestCase
):
324 self
.s
= Signal(max=self
.c
.nbits
)
326 def test_shape(self
):
327 s1
= self
.c
.word_select(self
.s
, 2)
328 self
.assertEqual(s1
.shape(), (2, False))
330 def test_stride(self
):
331 s1
= self
.c
.word_select(self
.s
, 2)
332 self
.assertEqual(s1
.stride
, 2)
334 def test_width_bad(self
):
335 with self
.assertRaises(TypeError):
336 self
.c
.word_select(self
.s
, 0)
337 with self
.assertRaises(TypeError):
338 self
.c
.word_select(self
.s
, -1)
341 s
= self
.c
.word_select(self
.s
, 2)
342 self
.assertEqual(repr(s
), "(part (const 8'd0) (sig s) 2 2)")
345 class CatTestCase(FHDLTestCase
):
346 def test_shape(self
):
348 self
.assertEqual(c0
.shape(), (0, False))
350 self
.assertEqual(c1
.shape(), (4, False))
351 c2
= Cat(Const(10), Const(1))
352 self
.assertEqual(c2
.shape(), (5, False))
353 c3
= Cat(Const(10), Const(1), Const(0))
354 self
.assertEqual(c3
.shape(), (6, False))
357 c1
= Cat(Const(10), Const(1))
358 self
.assertEqual(repr(c1
), "(cat (const 4'd10) (const 1'd1))")
361 class ReplTestCase(FHDLTestCase
):
362 def test_shape(self
):
363 s1
= Repl(Const(10), 3)
364 self
.assertEqual(s1
.shape(), (12, False))
365 s2
= Repl(Const(10), 0)
366 self
.assertEqual(s2
.shape(), (0, False))
368 def test_count_wrong(self
):
369 with self
.assertRaises(TypeError):
371 with self
.assertRaises(TypeError):
372 Repl(Const(10), "str")
375 s
= Repl(Const(10), 3)
376 self
.assertEqual(repr(s
), "(repl (const 4'd10) 3)")
379 class ArrayTestCase(FHDLTestCase
):
380 def test_acts_like_array(self
):
382 self
.assertSequenceEqual(a
, [1,2,3])
383 self
.assertEqual(a
[1], 2)
385 self
.assertSequenceEqual(a
, [1,4,3])
387 self
.assertSequenceEqual(a
, [1,3])
389 self
.assertSequenceEqual(a
, [1,2,3])
391 def test_becomes_immutable(self
):
393 s1
= Signal(max=len(a
))
394 s2
= Signal(max=len(a
))
397 with self
.assertRaisesRegex(ValueError,
398 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
400 with self
.assertRaisesRegex(ValueError,
401 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
403 with self
.assertRaisesRegex(ValueError,
404 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
409 self
.assertEqual(repr(a
), "(array mutable [1, 2, 3])")
410 s
= Signal(max=len(a
))
412 self
.assertEqual(repr(a
), "(array [1, 2, 3])")
415 class ArrayProxyTestCase(FHDLTestCase
):
416 def test_index_shape(self
):
417 m
= Array(Array(x
* y
for y
in range(1, 4)) for x
in range(1, 4))
421 self
.assertEqual(v
.shape(), (4, False))
423 def test_attr_shape(self
):
424 from collections
import namedtuple
425 pair
= namedtuple("pair", ("p", "n"))
426 a
= Array(pair(i
, -i
) for i
in range(10))
427 s
= Signal(max=len(a
))
429 self
.assertEqual(v
.p
.shape(), (4, False))
430 self
.assertEqual(v
.n
.shape(), (6, True))
436 self
.assertEqual(repr(v
), "(proxy (array [1, 2, 3]) (sig s))")
439 class SignalTestCase(FHDLTestCase
):
440 def test_shape(self
):
442 self
.assertEqual(s1
.shape(), (1, False))
444 self
.assertEqual(s2
.shape(), (2, False))
445 s3
= Signal((2, False))
446 self
.assertEqual(s3
.shape(), (2, False))
447 s4
= Signal((2, True))
448 self
.assertEqual(s4
.shape(), (2, True))
450 self
.assertEqual(s5
.shape(), (4, False))
451 s6
= Signal(min=4, max=16)
452 self
.assertEqual(s6
.shape(), (4, False))
453 s7
= Signal(min=-4, max=16)
454 self
.assertEqual(s7
.shape(), (5, True))
455 s8
= Signal(min=-20, max=16)
456 self
.assertEqual(s8
.shape(), (6, True))
458 self
.assertEqual(s9
.shape(), (0, False))
460 self
.assertEqual(s10
.shape(), (0, False))
462 def test_shape_bad(self
):
463 with self
.assertRaises(ValueError,
464 msg
="Lower bound 10 should be less or equal to higher bound 4"):
465 Signal(min=10, max=4)
466 with self
.assertRaises(ValueError,
467 msg
="Only one of bits/signedness or bounds may be specified"):
469 with self
.assertRaises(TypeError,
470 msg
="Width must be a non-negative integer, not '-10'"):
475 self
.assertEqual(s1
.name
, "s1")
476 s2
= Signal(name
="sig")
477 self
.assertEqual(s2
.name
, "sig")
479 def test_name_bad(self
):
480 with self
.assertRaises(TypeError,
481 msg
="Name must be a string, not 'True'"):
482 # A common typo: forgetting to put parens around width and signedness
485 def test_reset(self
):
486 s1
= Signal(4, reset
=0b111, reset_less
=True)
487 self
.assertEqual(s1
.reset
, 0b111)
488 self
.assertEqual(s1
.reset_less
, True)
490 def test_attrs(self
):
492 self
.assertEqual(s1
.attrs
, {})
493 s2
= Signal(attrs
={"no_retiming": True})
494 self
.assertEqual(s2
.attrs
, {"no_retiming": True})
498 self
.assertEqual(repr(s1
), "(sig s1)")
501 s1
= Signal
.like(Signal(4))
502 self
.assertEqual(s1
.shape(), (4, False))
503 s2
= Signal
.like(Signal(min=-15))
504 self
.assertEqual(s2
.shape(), (5, True))
505 s3
= Signal
.like(Signal(4, reset
=0b111, reset_less
=True))
506 self
.assertEqual(s3
.reset
, 0b111)
507 self
.assertEqual(s3
.reset_less
, True)
508 s4
= Signal
.like(Signal(attrs
={"no_retiming": True}))
509 self
.assertEqual(s4
.attrs
, {"no_retiming": True})
510 s5
= Signal
.like(Signal(decoder
=str))
511 self
.assertEqual(s5
.decoder
, str)
513 self
.assertEqual(s6
.shape(), (4, False))
514 s7
= [Signal
.like(Signal(4))][0]
515 self
.assertEqual(s7
.name
, "$like")
516 s8
= Signal
.like(s1
, name_suffix
="_ff")
517 self
.assertEqual(s8
.name
, "s1_ff")
519 def test_decoder(self
):
523 s
= Signal(decoder
=Color
)
524 self
.assertEqual(s
.decoder(1), "RED/1")
525 self
.assertEqual(s
.decoder(3), "3")
528 class ClockSignalTestCase(FHDLTestCase
):
529 def test_domain(self
):
531 self
.assertEqual(s1
.domain
, "sync")
532 s2
= ClockSignal("pix")
533 self
.assertEqual(s2
.domain
, "pix")
535 with self
.assertRaises(TypeError,
536 msg
="Clock domain name must be a string, not '1'"):
539 def test_shape(self
):
540 self
.assertEqual(ClockSignal().shape(), (1, False))
544 self
.assertEqual(repr(s1
), "(clk sync)")
546 def test_wrong_name_comb(self
):
547 with self
.assertRaises(ValueError,
548 msg
="Domain 'comb' does not have a clock"):
552 class ResetSignalTestCase(FHDLTestCase
):
553 def test_domain(self
):
555 self
.assertEqual(s1
.domain
, "sync")
556 s2
= ResetSignal("pix")
557 self
.assertEqual(s2
.domain
, "pix")
559 with self
.assertRaises(TypeError,
560 msg
="Clock domain name must be a string, not '1'"):
563 def test_shape(self
):
564 self
.assertEqual(ResetSignal().shape(), (1, False))
568 self
.assertEqual(repr(s1
), "(rst sync)")
570 def test_wrong_name_comb(self
):
571 with self
.assertRaises(ValueError,
572 msg
="Domain 'comb' does not have a reset"):
576 class MockUserValue(UserValue
):
577 def __init__(self
, lowered
):
580 self
.lowered
= lowered
583 self
.lower_count
+= 1
587 class UserValueTestCase(FHDLTestCase
):
588 def test_shape(self
):
589 uv
= MockUserValue(1)
590 self
.assertEqual(uv
.shape(), (1, False))
592 self
.assertEqual(uv
.shape(), (1, False))
593 self
.assertEqual(uv
.lower_count
, 1)
596 class SampleTestCase(FHDLTestCase
):
597 def test_const(self
):
598 s
= Sample(1, 1, "sync")
599 self
.assertEqual(s
.shape(), (1, False))
601 def test_signal(self
):
602 s1
= Sample(Signal(2), 1, "sync")
603 self
.assertEqual(s1
.shape(), (2, False))
604 s2
= Sample(ClockSignal(), 1, "sync")
605 s3
= Sample(ResetSignal(), 1, "sync")
607 def test_wrong_value_operator(self
):
608 with self
.assertRaises(TypeError,
609 "Sampled value may only be a signal or a constant, not "
610 "(+ (sig $signal) (const 1'd1))"):
611 Sample(Signal() + 1, 1, "sync")
613 def test_wrong_clocks_neg(self
):
614 with self
.assertRaises(ValueError,
615 "Cannot sample a value 1 cycles in the future"):
616 Sample(Signal(), -1, "sync")
619 class InitialTestCase(FHDLTestCase
):
620 def test_initial(self
):
622 self
.assertEqual(i
.shape(), (1, False))