lib.cdc: add tests for MultiReg.
[nmigen.git] / nmigen / test / test_sim.py
1 from contextlib import contextmanager
2
3 from .tools import *
4 from ..tools import flatten, union
5 from ..hdl.ast import *
6 from ..hdl.cd import *
7 from ..hdl.mem import *
8 from ..hdl.dsl import *
9 from ..hdl.ir import *
10 from ..back.pysim import *
11
12
13 class SimulatorUnitTestCase(FHDLTestCase):
14 def assertStatement(self, stmt, inputs, output, reset=0):
15 inputs = [Value.wrap(i) for i in inputs]
16 output = Value.wrap(output)
17
18 isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")]
19 osig = Signal(output.shape(), name="y", reset=reset)
20
21 stmt = stmt(osig, *isigs)
22 frag = Fragment()
23 frag.add_statements(stmt)
24 for signal in flatten(s._lhs_signals() for s in Statement.wrap(stmt)):
25 frag.add_driver(signal)
26
27 with Simulator(frag,
28 vcd_file =open("test.vcd", "w"),
29 gtkw_file=open("test.gtkw", "w"),
30 traces=[*isigs, osig]) as sim:
31 def process():
32 for isig, input in zip(isigs, inputs):
33 yield isig.eq(input)
34 yield Delay()
35 self.assertEqual((yield osig), output.value)
36 sim.add_process(process)
37 sim.run()
38
39 def test_invert(self):
40 stmt = lambda y, a: y.eq(~a)
41 self.assertStatement(stmt, [C(0b0000, 4)], C(0b1111, 4))
42 self.assertStatement(stmt, [C(0b1010, 4)], C(0b0101, 4))
43 self.assertStatement(stmt, [C(0, 4)], C(-1, 4))
44
45 def test_neg(self):
46 stmt = lambda y, a: y.eq(-a)
47 self.assertStatement(stmt, [C(0b0000, 4)], C(0b0000, 4))
48 self.assertStatement(stmt, [C(0b0001, 4)], C(0b1111, 4))
49 self.assertStatement(stmt, [C(0b1010, 4)], C(0b0110, 4))
50 self.assertStatement(stmt, [C(1, 4)], C(-1, 4))
51 self.assertStatement(stmt, [C(5, 4)], C(-5, 4))
52
53 def test_bool(self):
54 stmt = lambda y, a: y.eq(a.bool())
55 self.assertStatement(stmt, [C(0, 4)], C(0))
56 self.assertStatement(stmt, [C(1, 4)], C(1))
57 self.assertStatement(stmt, [C(2, 4)], C(1))
58
59 def test_add(self):
60 stmt = lambda y, a, b: y.eq(a + b)
61 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(1, 4))
62 self.assertStatement(stmt, [C(-5, 4), C(-5, 4)], C(-10, 5))
63
64 def test_sub(self):
65 stmt = lambda y, a, b: y.eq(a - b)
66 self.assertStatement(stmt, [C(2, 4), C(1, 4)], C(1, 4))
67 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(-1, 4))
68 self.assertStatement(stmt, [C(0, 4), C(10, 4)], C(-10, 5))
69
70 def test_mul(self):
71 stmt = lambda y, a, b: y.eq(a * b)
72 self.assertStatement(stmt, [C(2, 4), C(1, 4)], C(2, 8))
73 self.assertStatement(stmt, [C(2, 4), C(2, 4)], C(4, 8))
74 self.assertStatement(stmt, [C(7, 4), C(7, 4)], C(49, 8))
75
76 def test_and(self):
77 stmt = lambda y, a, b: y.eq(a & b)
78 self.assertStatement(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b1000, 4))
79
80 def test_or(self):
81 stmt = lambda y, a, b: y.eq(a | b)
82 self.assertStatement(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b1110, 4))
83
84 def test_xor(self):
85 stmt = lambda y, a, b: y.eq(a ^ b)
86 self.assertStatement(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b0110, 4))
87
88 def test_shl(self):
89 stmt = lambda y, a, b: y.eq(a << b)
90 self.assertStatement(stmt, [C(0b1001, 4), C(0)], C(0b1001, 5))
91 self.assertStatement(stmt, [C(0b1001, 4), C(3)], C(0b1001000, 7))
92 self.assertStatement(stmt, [C(0b1001, 4), C(-2)], C(0b10, 7))
93
94 def test_shr(self):
95 stmt = lambda y, a, b: y.eq(a >> b)
96 self.assertStatement(stmt, [C(0b1001, 4), C(0)], C(0b1001, 4))
97 self.assertStatement(stmt, [C(0b1001, 4), C(2)], C(0b10, 4))
98 self.assertStatement(stmt, [C(0b1001, 4), C(-2)], C(0b100100, 5))
99
100 def test_eq(self):
101 stmt = lambda y, a, b: y.eq(a == b)
102 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(1))
103 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(0))
104 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(0))
105
106 def test_ne(self):
107 stmt = lambda y, a, b: y.eq(a != b)
108 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(0))
109 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(1))
110 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(1))
111
112 def test_lt(self):
113 stmt = lambda y, a, b: y.eq(a < b)
114 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(0))
115 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(1))
116 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(0))
117
118 def test_ge(self):
119 stmt = lambda y, a, b: y.eq(a >= b)
120 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(1))
121 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(0))
122 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(1))
123
124 def test_gt(self):
125 stmt = lambda y, a, b: y.eq(a > b)
126 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(0))
127 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(0))
128 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(1))
129
130 def test_le(self):
131 stmt = lambda y, a, b: y.eq(a <= b)
132 self.assertStatement(stmt, [C(0, 4), C(0, 4)], C(1))
133 self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(1))
134 self.assertStatement(stmt, [C(1, 4), C(0, 4)], C(0))
135
136 def test_mux(self):
137 stmt = lambda y, a, b, c: y.eq(Mux(c, a, b))
138 self.assertStatement(stmt, [C(2, 4), C(3, 4), C(0)], C(3, 4))
139 self.assertStatement(stmt, [C(2, 4), C(3, 4), C(1)], C(2, 4))
140
141 def test_slice(self):
142 stmt1 = lambda y, a: y.eq(a[2])
143 self.assertStatement(stmt1, [C(0b10110100, 8)], C(0b1, 1))
144 stmt2 = lambda y, a: y.eq(a[2:4])
145 self.assertStatement(stmt2, [C(0b10110100, 8)], C(0b01, 2))
146
147 def test_slice_lhs(self):
148 stmt1 = lambda y, a: y[2].eq(a)
149 self.assertStatement(stmt1, [C(0b0, 1)], C(0b11111011, 8), reset=0b11111111)
150 stmt2 = lambda y, a: y[2:4].eq(a)
151 self.assertStatement(stmt2, [C(0b01, 2)], C(0b11110111, 8), reset=0b11111011)
152
153 def test_part(self):
154 stmt = lambda y, a, b: y.eq(a.part(b, 3))
155 self.assertStatement(stmt, [C(0b10110100, 8), C(0)], C(0b100, 3))
156 self.assertStatement(stmt, [C(0b10110100, 8), C(2)], C(0b101, 3))
157 self.assertStatement(stmt, [C(0b10110100, 8), C(3)], C(0b110, 3))
158
159 def test_part_lhs(self):
160 stmt = lambda y, a, b: y.part(a, 3).eq(b)
161 self.assertStatement(stmt, [C(0), C(0b100, 3)], C(0b11111100, 8), reset=0b11111111)
162 self.assertStatement(stmt, [C(2), C(0b101, 3)], C(0b11110111, 8), reset=0b11111111)
163 self.assertStatement(stmt, [C(3), C(0b110, 3)], C(0b11110111, 8), reset=0b11111111)
164
165 def test_cat(self):
166 stmt = lambda y, *xs: y.eq(Cat(*xs))
167 self.assertStatement(stmt, [C(0b10, 2), C(0b01, 2)], C(0b0110, 4))
168
169 def test_cat_lhs(self):
170 l = Signal(3)
171 m = Signal(3)
172 n = Signal(3)
173 stmt = lambda y, a: [Cat(l, m, n).eq(a), y.eq(Cat(n, m, l))]
174 self.assertStatement(stmt, [C(0b100101110, 9)], C(0b110101100, 9))
175
176 def test_repl(self):
177 stmt = lambda y, a: y.eq(Repl(a, 3))
178 self.assertStatement(stmt, [C(0b10, 2)], C(0b101010, 6))
179
180 def test_array(self):
181 array = Array([1, 4, 10])
182 stmt = lambda y, a: y.eq(array[a])
183 self.assertStatement(stmt, [C(0)], C(1))
184 self.assertStatement(stmt, [C(1)], C(4))
185 self.assertStatement(stmt, [C(2)], C(10))
186
187 def test_array_oob(self):
188 array = Array([1, 4, 10])
189 stmt = lambda y, a: y.eq(array[a])
190 self.assertStatement(stmt, [C(3)], C(10))
191 self.assertStatement(stmt, [C(4)], C(10))
192
193 def test_array_lhs(self):
194 l = Signal(3, reset=1)
195 m = Signal(3, reset=4)
196 n = Signal(3, reset=7)
197 array = Array([l, m, n])
198 stmt = lambda y, a, b: [array[a].eq(b), y.eq(Cat(*array))]
199 self.assertStatement(stmt, [C(0), C(0b000)], C(0b111100000))
200 self.assertStatement(stmt, [C(1), C(0b010)], C(0b111010001))
201 self.assertStatement(stmt, [C(2), C(0b100)], C(0b100100001))
202
203 def test_array_lhs_oob(self):
204 l = Signal(3)
205 m = Signal(3)
206 n = Signal(3)
207 array = Array([l, m, n])
208 stmt = lambda y, a, b: [array[a].eq(b), y.eq(Cat(*array))]
209 self.assertStatement(stmt, [C(3), C(0b001)], C(0b001000000))
210 self.assertStatement(stmt, [C(4), C(0b010)], C(0b010000000))
211
212 def test_array_index(self):
213 array = Array(Array(x * y for y in range(10)) for x in range(10))
214 stmt = lambda y, a, b: y.eq(array[a][b])
215 for x in range(10):
216 for y in range(10):
217 self.assertStatement(stmt, [C(x), C(y)], C(x * y))
218
219 def test_array_attr(self):
220 from collections import namedtuple
221 pair = namedtuple("pair", ("p", "n"))
222
223 array = Array(pair(x, -x) for x in range(10))
224 stmt = lambda y, a: y.eq(array[a].p + array[a].n)
225 for i in range(10):
226 self.assertStatement(stmt, [C(i)], C(0))
227
228
229 class SimulatorIntegrationTestCase(FHDLTestCase):
230 @contextmanager
231 def assertSimulation(self, module, deadline=None):
232 with Simulator(module.lower(platform=None)) as sim:
233 yield sim
234 if deadline is None:
235 sim.run()
236 else:
237 sim.run_until(deadline)
238
239 def setUp_counter(self):
240 self.count = Signal(3, reset=4)
241 self.sync = ClockDomain()
242
243 self.m = Module()
244 self.m.d.sync += self.count.eq(self.count + 1)
245 self.m.domains += self.sync
246
247 def test_counter_process(self):
248 self.setUp_counter()
249 with self.assertSimulation(self.m) as sim:
250 def process():
251 self.assertEqual((yield self.count), 4)
252 yield Delay(1e-6)
253 self.assertEqual((yield self.count), 4)
254 yield self.sync.clk.eq(1)
255 self.assertEqual((yield self.count), 5)
256 yield Delay(1e-6)
257 self.assertEqual((yield self.count), 5)
258 yield self.sync.clk.eq(0)
259 self.assertEqual((yield self.count), 5)
260 for _ in range(3):
261 yield Delay(1e-6)
262 yield self.sync.clk.eq(1)
263 yield Delay(1e-6)
264 yield self.sync.clk.eq(0)
265 self.assertEqual((yield self.count), 0)
266 sim.add_process(process)
267
268 def test_counter_clock_and_sync_process(self):
269 self.setUp_counter()
270 with self.assertSimulation(self.m) as sim:
271 sim.add_clock(1e-6, domain="sync")
272 def process():
273 self.assertEqual((yield self.count), 4)
274 self.assertEqual((yield self.sync.clk), 0)
275 yield
276 self.assertEqual((yield self.count), 5)
277 self.assertEqual((yield self.sync.clk), 1)
278 for _ in range(3):
279 yield
280 self.assertEqual((yield self.count), 0)
281 sim.add_sync_process(process)
282
283 def setUp_alu(self):
284 self.a = Signal(8)
285 self.b = Signal(8)
286 self.o = Signal(8)
287 self.x = Signal(8)
288 self.s = Signal(2)
289 self.sync = ClockDomain(reset_less=True)
290
291 self.m = Module()
292 self.m.d.comb += self.x.eq(self.a ^ self.b)
293 with self.m.Switch(self.s):
294 with self.m.Case(0):
295 self.m.d.sync += self.o.eq(self.a + self.b)
296 with self.m.Case(1):
297 self.m.d.sync += self.o.eq(self.a - self.b)
298 with self.m.Case():
299 self.m.d.sync += self.o.eq(0)
300 self.m.domains += self.sync
301
302 def test_alu(self):
303 self.setUp_alu()
304 with self.assertSimulation(self.m) as sim:
305 sim.add_clock(1e-6)
306 def process():
307 yield self.a.eq(5)
308 yield self.b.eq(1)
309 yield
310 self.assertEqual((yield self.x), 4)
311 self.assertEqual((yield self.o), 6)
312 yield self.s.eq(1)
313 yield
314 self.assertEqual((yield self.o), 4)
315 yield self.s.eq(2)
316 yield
317 self.assertEqual((yield self.o), 0)
318 sim.add_sync_process(process)
319
320 def setUp_multiclock(self):
321 self.sys = ClockDomain()
322 self.pix = ClockDomain()
323
324 self.m = Module()
325 self.m.domains += self.sys, self.pix
326
327 def test_multiclock(self):
328 self.setUp_multiclock()
329 with self.assertSimulation(self.m) as sim:
330 sim.add_clock(1e-6, domain="sys")
331 sim.add_clock(0.3e-6, domain="pix")
332
333 def sys_process():
334 yield Passive()
335 yield
336 yield
337 self.fail()
338 def pix_process():
339 yield
340 yield
341 yield
342 sim.add_sync_process(sys_process, domain="sys")
343 sim.add_sync_process(pix_process, domain="pix")
344
345 def setUp_lhs_rhs(self):
346 self.i = Signal(8)
347 self.o = Signal(8)
348
349 self.m = Module()
350 self.m.d.comb += self.o.eq(self.i)
351
352 def test_complex_lhs_rhs(self):
353 self.setUp_lhs_rhs()
354 with self.assertSimulation(self.m) as sim:
355 def process():
356 yield self.i.eq(0b10101010)
357 yield self.i[:4].eq(-1)
358 yield Delay()
359 self.assertEqual((yield self.i[:4]), 0b1111)
360 self.assertEqual((yield self.i), 0b10101111)
361 sim.add_process(process)
362
363 def test_run_until(self):
364 with self.assertSimulation(Module(), deadline=100e-6) as sim:
365 sim.add_clock(1e-6)
366 def process():
367 for _ in range(100):
368 yield
369 self.fail()
370
371 def test_add_process_wrong(self):
372 with self.assertSimulation(Module()) as sim:
373 with self.assertRaises(TypeError,
374 msg="Cannot add a process '1' because it is not a generator or "
375 "a generator function"):
376 sim.add_process(1)
377
378 def test_eq_signal_unused_wrong(self):
379 self.setUp_lhs_rhs()
380 self.s = Signal()
381 with self.assertSimulation(self.m) as sim:
382 def process():
383 with self.assertRaisesRegex(ValueError,
384 regex=r"Process '.+?' sent a request to set signal '\(sig s\)', "
385 r"which is not a part of simulation"):
386 yield self.s.eq(0)
387 yield Delay()
388 sim.add_process(process)
389
390 def test_eq_signal_comb_wrong(self):
391 self.setUp_lhs_rhs()
392 with self.assertSimulation(self.m) as sim:
393 def process():
394 with self.assertRaisesRegex(ValueError,
395 regex=r"Process '.+?' sent a request to set signal '\(sig o\)', "
396 r"which is a part of combinatorial assignment in simulation"):
397 yield self.o.eq(0)
398 yield Delay()
399 sim.add_process(process)
400
401 def test_command_wrong(self):
402 with self.assertSimulation(Module()) as sim:
403 def process():
404 with self.assertRaisesRegex(TypeError,
405 regex=r"Received unsupported command '1' from process '.+?'"):
406 yield 1
407 yield Delay()
408 sim.add_process(process)
409
410 def setUp_memory(self, rd_synchronous=True, rd_transparent=True, wr_granularity=None):
411 self.m = Module()
412 self.memory = Memory(width=8, depth=4, init=[0xaa, 0x55])
413 self.m.submodules.rdport = self.rdport = \
414 self.memory.read_port(synchronous=rd_synchronous, transparent=rd_transparent)
415 self.m.submodules.wrport = self.wrport = \
416 self.memory.write_port(granularity=wr_granularity)
417
418 def test_memory_init(self):
419 self.setUp_memory()
420 with self.assertSimulation(self.m) as sim:
421 def process():
422 self.assertEqual((yield self.rdport.data), 0xaa)
423 yield self.rdport.addr.eq(1)
424 yield
425 yield
426 self.assertEqual((yield self.rdport.data), 0x55)
427 yield self.rdport.addr.eq(2)
428 yield
429 yield
430 self.assertEqual((yield self.rdport.data), 0x00)
431 sim.add_clock(1e-6)
432 sim.add_sync_process(process)
433
434 def test_memory_write(self):
435 self.setUp_memory()
436 with self.assertSimulation(self.m) as sim:
437 def process():
438 yield self.wrport.addr.eq(4)
439 yield self.wrport.data.eq(0x33)
440 yield self.wrport.en.eq(1)
441 yield
442 yield self.wrport.en.eq(0)
443 yield self.rdport.addr.eq(4)
444 yield
445 self.assertEqual((yield self.rdport.data), 0x33)
446 sim.add_clock(1e-6)
447 sim.add_sync_process(process)
448
449 def test_memory_write_granularity(self):
450 self.setUp_memory(wr_granularity=4)
451 with self.assertSimulation(self.m) as sim:
452 def process():
453 yield self.wrport.data.eq(0x50)
454 yield self.wrport.en.eq(0b00)
455 yield
456 yield self.wrport.en.eq(0)
457 yield
458 self.assertEqual((yield self.rdport.data), 0xaa)
459 yield self.wrport.en.eq(0b10)
460 yield
461 yield self.wrport.en.eq(0)
462 yield
463 self.assertEqual((yield self.rdport.data), 0x5a)
464 yield self.wrport.data.eq(0x33)
465 yield self.wrport.en.eq(0b01)
466 yield
467 yield self.wrport.en.eq(0)
468 yield
469 self.assertEqual((yield self.rdport.data), 0x53)
470 sim.add_clock(1e-6)
471 sim.add_sync_process(process)
472
473 def test_memory_read_before_write(self):
474 self.setUp_memory(rd_transparent=False)
475 with self.assertSimulation(self.m) as sim:
476 def process():
477 yield self.wrport.data.eq(0x33)
478 yield self.wrport.en.eq(1)
479 yield self.rdport.en.eq(1)
480 yield
481 self.assertEqual((yield self.rdport.data), 0xaa)
482 yield Delay(1e-6) # let comb propagate
483 self.assertEqual((yield self.rdport.data), 0xaa)
484 sim.add_clock(1e-6)
485 sim.add_sync_process(process)
486
487 def test_memory_write_through(self):
488 self.setUp_memory(rd_transparent=True)
489 with self.assertSimulation(self.m) as sim:
490 def process():
491 yield self.wrport.data.eq(0x33)
492 yield self.wrport.en.eq(1)
493 yield
494 self.assertEqual((yield self.rdport.data), 0xaa)
495 yield Delay(1e-6) # let comb propagate
496 self.assertEqual((yield self.rdport.data), 0x33)
497 yield
498 yield self.rdport.addr.eq(1)
499 yield Delay(1e-6) # let comb propagate
500 self.assertEqual((yield self.rdport.data), 0x33)
501 sim.add_clock(1e-6)
502 sim.add_sync_process(process)
503
504 def test_memory_async_read_write(self):
505 self.setUp_memory(rd_synchronous=False)
506 with self.assertSimulation(self.m) as sim:
507 def process():
508 yield self.rdport.addr.eq(0)
509 yield Delay()
510 self.assertEqual((yield self.rdport.data), 0xaa)
511 yield self.rdport.addr.eq(1)
512 yield Delay()
513 self.assertEqual((yield self.rdport.data), 0x55)
514 yield self.rdport.addr.eq(0)
515 yield self.wrport.addr.eq(0)
516 yield self.wrport.data.eq(0x33)
517 yield self.wrport.en.eq(1)
518 yield Tick("sync")
519 self.assertEqual((yield self.rdport.data), 0xaa)
520 yield Delay(1e-6) # let comb propagate
521 self.assertEqual((yield self.rdport.data), 0x33)
522 sim.add_clock(1e-6)
523 sim.add_process(process)