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 PartTestCase(FHDLTestCase
):
300 self
.s
= Signal(max=self
.c
.nbits
)
302 def test_shape(self
):
303 s1
= self
.c
.part(self
.s
, 2)
304 self
.assertEqual(s1
.shape(), (2, False))
305 s2
= self
.c
.part(self
.s
, 0)
306 self
.assertEqual(s2
.shape(), (0, False))
308 def test_width_bad(self
):
309 with self
.assertRaises(TypeError):
310 self
.c
.part(self
.s
, -1)
313 s
= self
.c
.part(self
.s
, 2)
314 self
.assertEqual(repr(s
), "(part (const 8'd0) (sig s) 2)")
317 class CatTestCase(FHDLTestCase
):
318 def test_shape(self
):
320 self
.assertEqual(c0
.shape(), (0, False))
322 self
.assertEqual(c1
.shape(), (4, False))
323 c2
= Cat(Const(10), Const(1))
324 self
.assertEqual(c2
.shape(), (5, False))
325 c3
= Cat(Const(10), Const(1), Const(0))
326 self
.assertEqual(c3
.shape(), (6, False))
329 c1
= Cat(Const(10), Const(1))
330 self
.assertEqual(repr(c1
), "(cat (const 4'd10) (const 1'd1))")
333 class ReplTestCase(FHDLTestCase
):
334 def test_shape(self
):
335 s1
= Repl(Const(10), 3)
336 self
.assertEqual(s1
.shape(), (12, False))
337 s2
= Repl(Const(10), 0)
338 self
.assertEqual(s2
.shape(), (0, False))
340 def test_count_wrong(self
):
341 with self
.assertRaises(TypeError):
343 with self
.assertRaises(TypeError):
344 Repl(Const(10), "str")
347 s
= Repl(Const(10), 3)
348 self
.assertEqual(repr(s
), "(repl (const 4'd10) 3)")
351 class ArrayTestCase(FHDLTestCase
):
352 def test_acts_like_array(self
):
354 self
.assertSequenceEqual(a
, [1,2,3])
355 self
.assertEqual(a
[1], 2)
357 self
.assertSequenceEqual(a
, [1,4,3])
359 self
.assertSequenceEqual(a
, [1,3])
361 self
.assertSequenceEqual(a
, [1,2,3])
363 def test_becomes_immutable(self
):
365 s1
= Signal(max=len(a
))
366 s2
= Signal(max=len(a
))
369 with self
.assertRaisesRegex(ValueError,
370 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
372 with self
.assertRaisesRegex(ValueError,
373 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
375 with self
.assertRaisesRegex(ValueError,
376 regex
=r
"^Array can no longer be mutated after it was indexed with a value at "):
381 self
.assertEqual(repr(a
), "(array mutable [1, 2, 3])")
382 s
= Signal(max=len(a
))
384 self
.assertEqual(repr(a
), "(array [1, 2, 3])")
387 class ArrayProxyTestCase(FHDLTestCase
):
388 def test_index_shape(self
):
389 m
= Array(Array(x
* y
for y
in range(1, 4)) for x
in range(1, 4))
393 self
.assertEqual(v
.shape(), (4, False))
395 def test_attr_shape(self
):
396 from collections
import namedtuple
397 pair
= namedtuple("pair", ("p", "n"))
398 a
= Array(pair(i
, -i
) for i
in range(10))
399 s
= Signal(max=len(a
))
401 self
.assertEqual(v
.p
.shape(), (4, False))
402 self
.assertEqual(v
.n
.shape(), (6, True))
408 self
.assertEqual(repr(v
), "(proxy (array [1, 2, 3]) (sig s))")
411 class SignalTestCase(FHDLTestCase
):
412 def test_shape(self
):
414 self
.assertEqual(s1
.shape(), (1, False))
416 self
.assertEqual(s2
.shape(), (2, False))
417 s3
= Signal((2, False))
418 self
.assertEqual(s3
.shape(), (2, False))
419 s4
= Signal((2, True))
420 self
.assertEqual(s4
.shape(), (2, True))
422 self
.assertEqual(s5
.shape(), (4, False))
423 s6
= Signal(min=4, max=16)
424 self
.assertEqual(s6
.shape(), (4, False))
425 s7
= Signal(min=-4, max=16)
426 self
.assertEqual(s7
.shape(), (5, True))
427 s8
= Signal(min=-20, max=16)
428 self
.assertEqual(s8
.shape(), (6, True))
430 self
.assertEqual(s9
.shape(), (0, False))
432 self
.assertEqual(s10
.shape(), (0, False))
434 def test_shape_bad(self
):
435 with self
.assertRaises(ValueError,
436 msg
="Lower bound 10 should be less or equal to higher bound 4"):
437 Signal(min=10, max=4)
438 with self
.assertRaises(ValueError,
439 msg
="Only one of bits/signedness or bounds may be specified"):
441 with self
.assertRaises(TypeError,
442 msg
="Width must be a non-negative integer, not '-10'"):
447 self
.assertEqual(s1
.name
, "s1")
448 s2
= Signal(name
="sig")
449 self
.assertEqual(s2
.name
, "sig")
451 def test_name_bad(self
):
452 with self
.assertRaises(TypeError,
453 msg
="Name must be a string, not 'True'"):
454 # A common typo: forgetting to put parens around width and signedness
457 def test_reset(self
):
458 s1
= Signal(4, reset
=0b111, reset_less
=True)
459 self
.assertEqual(s1
.reset
, 0b111)
460 self
.assertEqual(s1
.reset_less
, True)
462 def test_attrs(self
):
464 self
.assertEqual(s1
.attrs
, {})
465 s2
= Signal(attrs
={"no_retiming": True})
466 self
.assertEqual(s2
.attrs
, {"no_retiming": True})
470 self
.assertEqual(repr(s1
), "(sig s1)")
473 s1
= Signal
.like(Signal(4))
474 self
.assertEqual(s1
.shape(), (4, False))
475 s2
= Signal
.like(Signal(min=-15))
476 self
.assertEqual(s2
.shape(), (5, True))
477 s3
= Signal
.like(Signal(4, reset
=0b111, reset_less
=True))
478 self
.assertEqual(s3
.reset
, 0b111)
479 self
.assertEqual(s3
.reset_less
, True)
480 s4
= Signal
.like(Signal(attrs
={"no_retiming": True}))
481 self
.assertEqual(s4
.attrs
, {"no_retiming": True})
482 s5
= Signal
.like(Signal(decoder
=str))
483 self
.assertEqual(s5
.decoder
, str)
485 self
.assertEqual(s6
.shape(), (4, False))
486 s7
= [Signal
.like(Signal(4))][0]
487 self
.assertEqual(s7
.name
, "$like")
488 s8
= Signal
.like(s1
, name_suffix
="_ff")
489 self
.assertEqual(s8
.name
, "s1_ff")
491 def test_decoder(self
):
495 s
= Signal(decoder
=Color
)
496 self
.assertEqual(s
.decoder(1), "RED/1")
497 self
.assertEqual(s
.decoder(3), "3")
500 class ClockSignalTestCase(FHDLTestCase
):
501 def test_domain(self
):
503 self
.assertEqual(s1
.domain
, "sync")
504 s2
= ClockSignal("pix")
505 self
.assertEqual(s2
.domain
, "pix")
507 with self
.assertRaises(TypeError,
508 msg
="Clock domain name must be a string, not '1'"):
511 def test_shape(self
):
512 self
.assertEqual(ClockSignal().shape(), (1, False))
516 self
.assertEqual(repr(s1
), "(clk sync)")
519 class ResetSignalTestCase(FHDLTestCase
):
520 def test_domain(self
):
522 self
.assertEqual(s1
.domain
, "sync")
523 s2
= ResetSignal("pix")
524 self
.assertEqual(s2
.domain
, "pix")
526 with self
.assertRaises(TypeError,
527 msg
="Clock domain name must be a string, not '1'"):
530 def test_shape(self
):
531 self
.assertEqual(ResetSignal().shape(), (1, False))
535 self
.assertEqual(repr(s1
), "(rst sync)")
538 class MockUserValue(UserValue
):
539 def __init__(self
, lowered
):
542 self
.lowered
= lowered
545 self
.lower_count
+= 1
549 class UserValueTestCase(FHDLTestCase
):
550 def test_shape(self
):
551 uv
= MockUserValue(1)
552 self
.assertEqual(uv
.shape(), (1, False))
554 self
.assertEqual(uv
.shape(), (1, False))
555 self
.assertEqual(uv
.lower_count
, 1)
558 class SampleTestCase(FHDLTestCase
):
559 def test_const(self
):
560 s
= Sample(1, 1, "sync")
561 self
.assertEqual(s
.shape(), (1, False))
563 def test_signal(self
):
564 s1
= Sample(Signal(2), 1, "sync")
565 self
.assertEqual(s1
.shape(), (2, False))
566 s2
= Sample(ClockSignal(), 1, "sync")
567 s3
= Sample(ResetSignal(), 1, "sync")
569 def test_wrong_value_operator(self
):
570 with self
.assertRaises(TypeError,
571 "Sampled value may only be a signal or a constant, not "
572 "(+ (sig $signal) (const 1'd1))"):
573 Sample(Signal() + 1, 1, "sync")
575 def test_wrong_clocks_neg(self
):
576 with self
.assertRaises(ValueError,
577 "Cannot sample a value 1 cycles in the future"):
578 Sample(Signal(), -1, "sync")