hdl.ast: add Value.{any,all}, mapping to $reduce_{or,and}.
[nmigen.git] / nmigen / test / test_hdl_ast.py
1 import warnings
2 from enum import Enum
3
4 from ..hdl.ast import *
5 from .tools import *
6
7
8 class ValueTestCase(FHDLTestCase):
9 def test_wrap(self):
10 self.assertIsInstance(Value.wrap(0), Const)
11 self.assertIsInstance(Value.wrap(True), Const)
12 c = Const(0)
13 self.assertIs(Value.wrap(c), c)
14 with self.assertRaises(TypeError,
15 msg="Object ''str'' is not an nMigen value"):
16 Value.wrap("str")
17
18 def test_bool(self):
19 with self.assertRaises(TypeError,
20 msg="Attempted to convert nMigen value to boolean"):
21 if Const(0):
22 pass
23
24 def test_len(self):
25 self.assertEqual(len(Const(10)), 4)
26
27 def test_getitem_int(self):
28 s1 = Const(10)[0]
29 self.assertIsInstance(s1, Slice)
30 self.assertEqual(s1.start, 0)
31 self.assertEqual(s1.end, 1)
32 s2 = Const(10)[-1]
33 self.assertIsInstance(s2, Slice)
34 self.assertEqual(s2.start, 3)
35 self.assertEqual(s2.end, 4)
36 with self.assertRaises(IndexError,
37 msg="Cannot index 5 bits into 4-bit value"):
38 Const(10)[5]
39
40 def test_getitem_slice(self):
41 s1 = Const(10)[1:3]
42 self.assertIsInstance(s1, Slice)
43 self.assertEqual(s1.start, 1)
44 self.assertEqual(s1.end, 3)
45 s2 = Const(10)[1:-2]
46 self.assertIsInstance(s2, Slice)
47 self.assertEqual(s2.start, 1)
48 self.assertEqual(s2.end, 2)
49 s3 = Const(31)[::2]
50 self.assertIsInstance(s3, Cat)
51 self.assertIsInstance(s3.parts[0], Slice)
52 self.assertEqual(s3.parts[0].start, 0)
53 self.assertEqual(s3.parts[0].end, 1)
54 self.assertIsInstance(s3.parts[1], Slice)
55 self.assertEqual(s3.parts[1].start, 2)
56 self.assertEqual(s3.parts[1].end, 3)
57 self.assertIsInstance(s3.parts[2], Slice)
58 self.assertEqual(s3.parts[2].start, 4)
59 self.assertEqual(s3.parts[2].end, 5)
60
61 def test_getitem_wrong(self):
62 with self.assertRaises(TypeError,
63 msg="Cannot index value with 'str'"):
64 Const(31)["str"]
65
66
67 class ConstTestCase(FHDLTestCase):
68 def test_shape(self):
69 self.assertEqual(Const(0).shape(), (1, False))
70 self.assertEqual(Const(1).shape(), (1, False))
71 self.assertEqual(Const(10).shape(), (4, False))
72 self.assertEqual(Const(-10).shape(), (5, True))
73
74 self.assertEqual(Const(1, 4).shape(), (4, False))
75 self.assertEqual(Const(1, (4, True)).shape(), (4, True))
76 self.assertEqual(Const(0, (0, False)).shape(), (0, False))
77
78 def test_shape_bad(self):
79 with self.assertRaises(TypeError,
80 msg="Width must be a non-negative integer, not '-1'"):
81 Const(1, -1)
82
83 def test_normalization(self):
84 self.assertEqual(Const(0b10110, (5, True)).value, -10)
85
86 def test_value(self):
87 self.assertEqual(Const(10).value, 10)
88
89 def test_repr(self):
90 self.assertEqual(repr(Const(10)), "(const 4'd10)")
91 self.assertEqual(repr(Const(-10)), "(const 5'sd-10)")
92
93 def test_hash(self):
94 with self.assertRaises(TypeError):
95 hash(Const(0))
96
97
98 class OperatorTestCase(FHDLTestCase):
99 def test_bool(self):
100 v = Const(0, 4).bool()
101 self.assertEqual(repr(v), "(b (const 4'd0))")
102 self.assertEqual(v.shape(), (1, False))
103
104 def test_invert(self):
105 v = ~Const(0, 4)
106 self.assertEqual(repr(v), "(~ (const 4'd0))")
107 self.assertEqual(v.shape(), (4, False))
108
109 def test_neg(self):
110 v1 = -Const(0, (4, False))
111 self.assertEqual(repr(v1), "(- (const 4'd0))")
112 self.assertEqual(v1.shape(), (5, True))
113 v2 = -Const(0, (4, True))
114 self.assertEqual(repr(v2), "(- (const 4'sd0))")
115 self.assertEqual(v2.shape(), (4, True))
116
117 def test_add(self):
118 v1 = Const(0, (4, False)) + Const(0, (6, False))
119 self.assertEqual(repr(v1), "(+ (const 4'd0) (const 6'd0))")
120 self.assertEqual(v1.shape(), (7, False))
121 v2 = Const(0, (4, True)) + Const(0, (6, True))
122 self.assertEqual(v2.shape(), (7, True))
123 v3 = Const(0, (4, True)) + Const(0, (4, False))
124 self.assertEqual(v3.shape(), (6, True))
125 v4 = Const(0, (4, False)) + Const(0, (4, True))
126 self.assertEqual(v4.shape(), (6, True))
127 v5 = 10 + Const(0, 4)
128 self.assertEqual(v5.shape(), (5, False))
129
130 def test_sub(self):
131 v1 = Const(0, (4, False)) - Const(0, (6, False))
132 self.assertEqual(repr(v1), "(- (const 4'd0) (const 6'd0))")
133 self.assertEqual(v1.shape(), (7, False))
134 v2 = Const(0, (4, True)) - Const(0, (6, True))
135 self.assertEqual(v2.shape(), (7, True))
136 v3 = Const(0, (4, True)) - Const(0, (4, False))
137 self.assertEqual(v3.shape(), (6, True))
138 v4 = Const(0, (4, False)) - Const(0, (4, True))
139 self.assertEqual(v4.shape(), (6, True))
140 v5 = 10 - Const(0, 4)
141 self.assertEqual(v5.shape(), (5, False))
142
143 def test_mul(self):
144 v1 = Const(0, (4, False)) * Const(0, (6, False))
145 self.assertEqual(repr(v1), "(* (const 4'd0) (const 6'd0))")
146 self.assertEqual(v1.shape(), (10, False))
147 v2 = Const(0, (4, True)) * Const(0, (6, True))
148 self.assertEqual(v2.shape(), (10, True))
149 v3 = Const(0, (4, True)) * Const(0, (4, False))
150 self.assertEqual(v3.shape(), (8, True))
151 v5 = 10 * Const(0, 4)
152 self.assertEqual(v5.shape(), (8, False))
153
154 def test_and(self):
155 v1 = Const(0, (4, False)) & Const(0, (6, False))
156 self.assertEqual(repr(v1), "(& (const 4'd0) (const 6'd0))")
157 self.assertEqual(v1.shape(), (6, False))
158 v2 = Const(0, (4, True)) & Const(0, (6, True))
159 self.assertEqual(v2.shape(), (6, True))
160 v3 = Const(0, (4, True)) & Const(0, (4, False))
161 self.assertEqual(v3.shape(), (5, True))
162 v4 = Const(0, (4, False)) & Const(0, (4, True))
163 self.assertEqual(v4.shape(), (5, True))
164 v5 = 10 & Const(0, 4)
165 self.assertEqual(v5.shape(), (4, False))
166
167 def test_or(self):
168 v1 = Const(0, (4, False)) | Const(0, (6, False))
169 self.assertEqual(repr(v1), "(| (const 4'd0) (const 6'd0))")
170 self.assertEqual(v1.shape(), (6, False))
171 v2 = Const(0, (4, True)) | Const(0, (6, True))
172 self.assertEqual(v2.shape(), (6, True))
173 v3 = Const(0, (4, True)) | Const(0, (4, False))
174 self.assertEqual(v3.shape(), (5, True))
175 v4 = Const(0, (4, False)) | Const(0, (4, True))
176 self.assertEqual(v4.shape(), (5, True))
177 v5 = 10 | Const(0, 4)
178 self.assertEqual(v5.shape(), (4, False))
179
180 def test_xor(self):
181 v1 = Const(0, (4, False)) ^ Const(0, (6, False))
182 self.assertEqual(repr(v1), "(^ (const 4'd0) (const 6'd0))")
183 self.assertEqual(v1.shape(), (6, False))
184 v2 = Const(0, (4, True)) ^ Const(0, (6, True))
185 self.assertEqual(v2.shape(), (6, True))
186 v3 = Const(0, (4, True)) ^ Const(0, (4, False))
187 self.assertEqual(v3.shape(), (5, True))
188 v4 = Const(0, (4, False)) ^ Const(0, (4, True))
189 self.assertEqual(v4.shape(), (5, True))
190 v5 = 10 ^ Const(0, 4)
191 self.assertEqual(v5.shape(), (4, False))
192
193 def test_shl(self):
194 v1 = Const(1, 4) << Const(4)
195 self.assertEqual(repr(v1), "(<< (const 4'd1) (const 3'd4))")
196 self.assertEqual(v1.shape(), (11, False))
197 v2 = Const(1, 4) << Const(-3)
198 self.assertEqual(v2.shape(), (7, False))
199
200 def test_shr(self):
201 v1 = Const(1, 4) >> Const(4)
202 self.assertEqual(repr(v1), "(>> (const 4'd1) (const 3'd4))")
203 self.assertEqual(v1.shape(), (4, False))
204 v2 = Const(1, 4) >> Const(-3)
205 self.assertEqual(v2.shape(), (8, False))
206
207 def test_lt(self):
208 v = Const(0, 4) < Const(0, 6)
209 self.assertEqual(repr(v), "(< (const 4'd0) (const 6'd0))")
210 self.assertEqual(v.shape(), (1, False))
211
212 def test_le(self):
213 v = Const(0, 4) <= Const(0, 6)
214 self.assertEqual(repr(v), "(<= (const 4'd0) (const 6'd0))")
215 self.assertEqual(v.shape(), (1, False))
216
217 def test_gt(self):
218 v = Const(0, 4) > Const(0, 6)
219 self.assertEqual(repr(v), "(> (const 4'd0) (const 6'd0))")
220 self.assertEqual(v.shape(), (1, False))
221
222 def test_ge(self):
223 v = Const(0, 4) >= Const(0, 6)
224 self.assertEqual(repr(v), "(>= (const 4'd0) (const 6'd0))")
225 self.assertEqual(v.shape(), (1, False))
226
227 def test_eq(self):
228 v = Const(0, 4) == Const(0, 6)
229 self.assertEqual(repr(v), "(== (const 4'd0) (const 6'd0))")
230 self.assertEqual(v.shape(), (1, False))
231
232 def test_ne(self):
233 v = Const(0, 4) != Const(0, 6)
234 self.assertEqual(repr(v), "(!= (const 4'd0) (const 6'd0))")
235 self.assertEqual(v.shape(), (1, False))
236
237 def test_mux(self):
238 s = Const(0)
239 v1 = Mux(s, Const(0, (4, False)), Const(0, (6, False)))
240 self.assertEqual(repr(v1), "(m (const 1'd0) (const 4'd0) (const 6'd0))")
241 self.assertEqual(v1.shape(), (6, False))
242 v2 = Mux(s, Const(0, (4, True)), Const(0, (6, True)))
243 self.assertEqual(v2.shape(), (6, True))
244 v3 = Mux(s, Const(0, (4, True)), Const(0, (4, False)))
245 self.assertEqual(v3.shape(), (5, True))
246 v4 = Mux(s, Const(0, (4, False)), Const(0, (4, True)))
247 self.assertEqual(v4.shape(), (5, True))
248
249 def test_bool(self):
250 v = Const(0).bool()
251 self.assertEqual(repr(v), "(b (const 1'd0))")
252 self.assertEqual(v.shape(), (1, False))
253
254 def test_any(self):
255 v = Const(0b101).any()
256 self.assertEqual(repr(v), "(r| (const 3'd5))")
257
258 def test_all(self):
259 v = Const(0b101).all()
260 self.assertEqual(repr(v), "(r& (const 3'd5))")
261
262 def test_hash(self):
263 with self.assertRaises(TypeError):
264 hash(Const(0) + Const(0))
265
266
267 class SliceTestCase(FHDLTestCase):
268 def test_shape(self):
269 s1 = Const(10)[2]
270 self.assertEqual(s1.shape(), (1, False))
271 s2 = Const(-10)[0:2]
272 self.assertEqual(s2.shape(), (2, False))
273
274 def test_start_end_negative(self):
275 c = Const(0, 8)
276 s1 = Slice(c, 0, -1)
277 self.assertEqual((s1.start, s1.end), (0, 7))
278 s1 = Slice(c, -4, -1)
279 self.assertEqual((s1.start, s1.end), (4, 7))
280
281 def test_start_end_wrong(self):
282 with self.assertRaises(TypeError,
283 msg="Slice start must be an integer, not ''x''"):
284 Slice(0, "x", 1)
285 with self.assertRaises(TypeError,
286 msg="Slice end must be an integer, not ''x''"):
287 Slice(0, 1, "x")
288
289 def test_start_end_out_of_range(self):
290 c = Const(0, 8)
291 with self.assertRaises(IndexError,
292 msg="Cannot start slice 10 bits into 8-bit value"):
293 Slice(c, 10, 12)
294 with self.assertRaises(IndexError,
295 msg="Cannot end slice 12 bits into 8-bit value"):
296 Slice(c, 0, 12)
297 with self.assertRaises(IndexError,
298 msg="Slice start 4 must be less than slice end 2"):
299 Slice(c, 4, 2)
300
301 def test_repr(self):
302 s1 = Const(10)[2]
303 self.assertEqual(repr(s1), "(slice (const 4'd10) 2:3)")
304
305
306 class BitSelectTestCase(FHDLTestCase):
307 def setUp(self):
308 self.c = Const(0, 8)
309 self.s = Signal.range(self.c.nbits)
310
311 def test_shape(self):
312 s1 = self.c.bit_select(self.s, 2)
313 self.assertEqual(s1.shape(), (2, False))
314 s2 = self.c.bit_select(self.s, 0)
315 self.assertEqual(s2.shape(), (0, False))
316
317 def test_stride(self):
318 s1 = self.c.bit_select(self.s, 2)
319 self.assertEqual(s1.stride, 1)
320
321 def test_width_bad(self):
322 with self.assertRaises(TypeError):
323 self.c.bit_select(self.s, -1)
324
325 def test_repr(self):
326 s = self.c.bit_select(self.s, 2)
327 self.assertEqual(repr(s), "(part (const 8'd0) (sig s) 2 1)")
328
329
330 class WordSelectTestCase(FHDLTestCase):
331 def setUp(self):
332 self.c = Const(0, 8)
333 self.s = Signal.range(self.c.nbits)
334
335 def test_shape(self):
336 s1 = self.c.word_select(self.s, 2)
337 self.assertEqual(s1.shape(), (2, False))
338
339 def test_stride(self):
340 s1 = self.c.word_select(self.s, 2)
341 self.assertEqual(s1.stride, 2)
342
343 def test_width_bad(self):
344 with self.assertRaises(TypeError):
345 self.c.word_select(self.s, 0)
346 with self.assertRaises(TypeError):
347 self.c.word_select(self.s, -1)
348
349 def test_repr(self):
350 s = self.c.word_select(self.s, 2)
351 self.assertEqual(repr(s), "(part (const 8'd0) (sig s) 2 2)")
352
353
354 class CatTestCase(FHDLTestCase):
355 def test_shape(self):
356 c0 = Cat()
357 self.assertEqual(c0.shape(), (0, False))
358 c1 = Cat(Const(10))
359 self.assertEqual(c1.shape(), (4, False))
360 c2 = Cat(Const(10), Const(1))
361 self.assertEqual(c2.shape(), (5, False))
362 c3 = Cat(Const(10), Const(1), Const(0))
363 self.assertEqual(c3.shape(), (6, False))
364
365 def test_repr(self):
366 c1 = Cat(Const(10), Const(1))
367 self.assertEqual(repr(c1), "(cat (const 4'd10) (const 1'd1))")
368
369
370 class ReplTestCase(FHDLTestCase):
371 def test_shape(self):
372 s1 = Repl(Const(10), 3)
373 self.assertEqual(s1.shape(), (12, False))
374 s2 = Repl(Const(10), 0)
375 self.assertEqual(s2.shape(), (0, False))
376
377 def test_count_wrong(self):
378 with self.assertRaises(TypeError):
379 Repl(Const(10), -1)
380 with self.assertRaises(TypeError):
381 Repl(Const(10), "str")
382
383 def test_repr(self):
384 s = Repl(Const(10), 3)
385 self.assertEqual(repr(s), "(repl (const 4'd10) 3)")
386
387
388 class ArrayTestCase(FHDLTestCase):
389 def test_acts_like_array(self):
390 a = Array([1,2,3])
391 self.assertSequenceEqual(a, [1,2,3])
392 self.assertEqual(a[1], 2)
393 a[1] = 4
394 self.assertSequenceEqual(a, [1,4,3])
395 del a[1]
396 self.assertSequenceEqual(a, [1,3])
397 a.insert(1, 2)
398 self.assertSequenceEqual(a, [1,2,3])
399
400 def test_becomes_immutable(self):
401 a = Array([1,2,3])
402 s1 = Signal.range(len(a))
403 s2 = Signal.range(len(a))
404 v1 = a[s1]
405 v2 = a[s2]
406 with self.assertRaisesRegex(ValueError,
407 regex=r"^Array can no longer be mutated after it was indexed with a value at "):
408 a[1] = 2
409 with self.assertRaisesRegex(ValueError,
410 regex=r"^Array can no longer be mutated after it was indexed with a value at "):
411 del a[1]
412 with self.assertRaisesRegex(ValueError,
413 regex=r"^Array can no longer be mutated after it was indexed with a value at "):
414 a.insert(1, 2)
415
416 def test_repr(self):
417 a = Array([1,2,3])
418 self.assertEqual(repr(a), "(array mutable [1, 2, 3])")
419 s = Signal.range(len(a))
420 v = a[s]
421 self.assertEqual(repr(a), "(array [1, 2, 3])")
422
423
424 class ArrayProxyTestCase(FHDLTestCase):
425 def test_index_shape(self):
426 m = Array(Array(x * y for y in range(1, 4)) for x in range(1, 4))
427 a = Signal.range(3)
428 b = Signal.range(3)
429 v = m[a][b]
430 self.assertEqual(v.shape(), (4, False))
431
432 def test_attr_shape(self):
433 from collections import namedtuple
434 pair = namedtuple("pair", ("p", "n"))
435 a = Array(pair(i, -i) for i in range(10))
436 s = Signal.range(len(a))
437 v = a[s]
438 self.assertEqual(v.p.shape(), (4, False))
439 self.assertEqual(v.n.shape(), (6, True))
440
441 def test_repr(self):
442 a = Array([1, 2, 3])
443 s = Signal.range(3)
444 v = a[s]
445 self.assertEqual(repr(v), "(proxy (array [1, 2, 3]) (sig s))")
446
447
448 class SignalTestCase(FHDLTestCase):
449 def test_shape(self):
450 s1 = Signal()
451 self.assertEqual(s1.shape(), (1, False))
452 s2 = Signal(2)
453 self.assertEqual(s2.shape(), (2, False))
454 s3 = Signal((2, False))
455 self.assertEqual(s3.shape(), (2, False))
456 s4 = Signal((2, True))
457 self.assertEqual(s4.shape(), (2, True))
458 s5 = Signal(0)
459 self.assertEqual(s5.shape(), (0, False))
460 s6 = Signal.range(16)
461 self.assertEqual(s6.shape(), (4, False))
462 s7 = Signal.range(4, 16)
463 self.assertEqual(s7.shape(), (4, False))
464 s8 = Signal.range(-4, 16)
465 self.assertEqual(s8.shape(), (5, True))
466 s9 = Signal.range(-20, 16)
467 self.assertEqual(s9.shape(), (6, True))
468 s10 = Signal.range(0)
469 self.assertEqual(s10.shape(), (1, False))
470 s11 = Signal.range(1)
471 self.assertEqual(s11.shape(), (1, False))
472 # deprecated
473 with warnings.catch_warnings():
474 warnings.filterwarnings(action="ignore", category=DeprecationWarning)
475 d6 = Signal(max=16)
476 self.assertEqual(d6.shape(), (4, False))
477 d7 = Signal(min=4, max=16)
478 self.assertEqual(d7.shape(), (4, False))
479 d8 = Signal(min=-4, max=16)
480 self.assertEqual(d8.shape(), (5, True))
481 d9 = Signal(min=-20, max=16)
482 self.assertEqual(d9.shape(), (6, True))
483 d10 = Signal(max=1)
484 self.assertEqual(d10.shape(), (0, False))
485
486 def test_shape_bad(self):
487 with self.assertRaises(TypeError,
488 msg="Width must be a non-negative integer, not '-10'"):
489 Signal(-10)
490
491 def test_min_max_deprecated(self):
492 with self.assertWarns(DeprecationWarning,
493 msg="instead of `Signal(min=0, max=10)`, use `Signal.range(0, 10)`"):
494 Signal(max=10)
495 with warnings.catch_warnings():
496 warnings.filterwarnings(action="ignore", category=DeprecationWarning)
497 with self.assertRaises(ValueError,
498 msg="Lower bound 10 should be less or equal to higher bound 4"):
499 Signal(min=10, max=4)
500 with self.assertRaises(ValueError,
501 msg="Only one of bits/signedness or bounds may be specified"):
502 Signal(2, min=10)
503
504 def test_name(self):
505 s1 = Signal()
506 self.assertEqual(s1.name, "s1")
507 s2 = Signal(name="sig")
508 self.assertEqual(s2.name, "sig")
509
510 def test_name_bad(self):
511 with self.assertRaises(TypeError,
512 msg="Name must be a string, not 'True'"):
513 # A common typo: forgetting to put parens around width and signedness
514 Signal(1, True)
515
516 def test_reset(self):
517 s1 = Signal(4, reset=0b111, reset_less=True)
518 self.assertEqual(s1.reset, 0b111)
519 self.assertEqual(s1.reset_less, True)
520
521 def test_reset_narrow(self):
522 with self.assertWarns(SyntaxWarning,
523 msg="Reset value 8 requires 4 bits to represent, but the signal only has 3 bits"):
524 Signal(3, reset=8)
525 with self.assertWarns(SyntaxWarning,
526 msg="Reset value 4 requires 4 bits to represent, but the signal only has 3 bits"):
527 Signal((3, True), reset=4)
528 with self.assertWarns(SyntaxWarning,
529 msg="Reset value -5 requires 4 bits to represent, but the signal only has 3 bits"):
530 Signal((3, True), reset=-5)
531
532 def test_attrs(self):
533 s1 = Signal()
534 self.assertEqual(s1.attrs, {})
535 s2 = Signal(attrs={"no_retiming": True})
536 self.assertEqual(s2.attrs, {"no_retiming": True})
537
538 def test_repr(self):
539 s1 = Signal()
540 self.assertEqual(repr(s1), "(sig s1)")
541
542 def test_like(self):
543 s1 = Signal.like(Signal(4))
544 self.assertEqual(s1.shape(), (4, False))
545 s2 = Signal.like(Signal.range(-15, 1))
546 self.assertEqual(s2.shape(), (5, True))
547 s3 = Signal.like(Signal(4, reset=0b111, reset_less=True))
548 self.assertEqual(s3.reset, 0b111)
549 self.assertEqual(s3.reset_less, True)
550 s4 = Signal.like(Signal(attrs={"no_retiming": True}))
551 self.assertEqual(s4.attrs, {"no_retiming": True})
552 s5 = Signal.like(Signal(decoder=str))
553 self.assertEqual(s5.decoder, str)
554 s6 = Signal.like(10)
555 self.assertEqual(s6.shape(), (4, False))
556 s7 = [Signal.like(Signal(4))][0]
557 self.assertEqual(s7.name, "$like")
558 s8 = Signal.like(s1, name_suffix="_ff")
559 self.assertEqual(s8.name, "s1_ff")
560
561 def test_decoder(self):
562 class Color(Enum):
563 RED = 1
564 BLUE = 2
565 s = Signal(decoder=Color)
566 self.assertEqual(s.decoder(1), "RED/1")
567 self.assertEqual(s.decoder(3), "3")
568
569
570 class ClockSignalTestCase(FHDLTestCase):
571 def test_domain(self):
572 s1 = ClockSignal()
573 self.assertEqual(s1.domain, "sync")
574 s2 = ClockSignal("pix")
575 self.assertEqual(s2.domain, "pix")
576
577 with self.assertRaises(TypeError,
578 msg="Clock domain name must be a string, not '1'"):
579 ClockSignal(1)
580
581 def test_shape(self):
582 self.assertEqual(ClockSignal().shape(), (1, False))
583
584 def test_repr(self):
585 s1 = ClockSignal()
586 self.assertEqual(repr(s1), "(clk sync)")
587
588 def test_wrong_name_comb(self):
589 with self.assertRaises(ValueError,
590 msg="Domain 'comb' does not have a clock"):
591 ClockSignal("comb")
592
593
594 class ResetSignalTestCase(FHDLTestCase):
595 def test_domain(self):
596 s1 = ResetSignal()
597 self.assertEqual(s1.domain, "sync")
598 s2 = ResetSignal("pix")
599 self.assertEqual(s2.domain, "pix")
600
601 with self.assertRaises(TypeError,
602 msg="Clock domain name must be a string, not '1'"):
603 ResetSignal(1)
604
605 def test_shape(self):
606 self.assertEqual(ResetSignal().shape(), (1, False))
607
608 def test_repr(self):
609 s1 = ResetSignal()
610 self.assertEqual(repr(s1), "(rst sync)")
611
612 def test_wrong_name_comb(self):
613 with self.assertRaises(ValueError,
614 msg="Domain 'comb' does not have a reset"):
615 ResetSignal("comb")
616
617
618 class MockUserValue(UserValue):
619 def __init__(self, lowered):
620 super().__init__()
621 self.lower_count = 0
622 self.lowered = lowered
623
624 def lower(self):
625 self.lower_count += 1
626 return self.lowered
627
628
629 class UserValueTestCase(FHDLTestCase):
630 def test_shape(self):
631 uv = MockUserValue(1)
632 self.assertEqual(uv.shape(), (1, False))
633 uv.lowered = 2
634 self.assertEqual(uv.shape(), (1, False))
635 self.assertEqual(uv.lower_count, 1)
636
637
638 class SampleTestCase(FHDLTestCase):
639 def test_const(self):
640 s = Sample(1, 1, "sync")
641 self.assertEqual(s.shape(), (1, False))
642
643 def test_signal(self):
644 s1 = Sample(Signal(2), 1, "sync")
645 self.assertEqual(s1.shape(), (2, False))
646 s2 = Sample(ClockSignal(), 1, "sync")
647 s3 = Sample(ResetSignal(), 1, "sync")
648
649 def test_wrong_value_operator(self):
650 with self.assertRaises(TypeError,
651 "Sampled value must be a signal or a constant, not "
652 "(+ (sig $signal) (const 1'd1))"):
653 Sample(Signal() + 1, 1, "sync")
654
655 def test_wrong_clocks_neg(self):
656 with self.assertRaises(ValueError,
657 "Cannot sample a value 1 cycles in the future"):
658 Sample(Signal(), -1, "sync")
659
660 def test_wrong_domain(self):
661 with self.assertRaises(TypeError,
662 "Domain name must be a string or None, not 0"):
663 Sample(Signal(), 1, 0)
664
665
666 class InitialTestCase(FHDLTestCase):
667 def test_initial(self):
668 i = Initial()
669 self.assertEqual(i.shape(), (1, False))