test: move to sim = Simulator(dut) instead of context manager.
[lambdasoc.git] / lambdasoc / test / test_periph_sram.py
1 #nmigen: UnusedElaboratable=no
2
3 import unittest
4
5 from nmigen import *
6 from nmigen.utils import log2_int
7 from nmigen.back.pysim import *
8
9 from nmigen_soc.wishbone import CycleType, BurstTypeExt
10
11 from ._wishbone import *
12 from ..periph.sram import SRAMPeripheral
13
14
15 def simulation_test(dut, process):
16 sim = Simulator(dut)
17 sim.add_clock(1e-6)
18 sim.add_sync_process(process)
19 with sim.write_vcd("test.vcd"):
20 sim.run()
21
22
23 def _burst_type(wrap):
24 if wrap == 0:
25 return BurstTypeExt.LINEAR
26 if wrap == 4:
27 return BurstTypeExt.WRAP_4
28 if wrap == 8:
29 return BurstTypeExt.WRAP_8
30 if wrap == 16:
31 return BurstTypeExt.WRAP_16
32 assert False
33
34
35 class SRAMPeripheralTestCase(unittest.TestCase):
36 def read_incr(self, dut, *, addr, count, wrap=0): # FIXME clean
37 data = []
38 yield dut.bus.cyc.eq(1)
39 yield dut.bus.stb.eq(1)
40 yield dut.bus.adr.eq(addr)
41 yield dut.bus.bte.eq(_burst_type(wrap))
42 yield dut.bus.cti.eq(CycleType.END_OF_BURST if count == 0 else CycleType.INCR_BURST)
43 yield
44 self.assertFalse((yield dut.bus.ack))
45 for i in range(count):
46 yield
47 self.assertTrue((yield dut.bus.ack))
48 data.append((yield dut.bus.dat_r))
49 if wrap == 0:
50 yield dut.bus.adr.eq((yield dut.bus.adr) + 1)
51 else:
52 yield dut.bus.adr[:log2_int(wrap)].eq((yield dut.bus.adr[:log2_int(wrap)]) + 1)
53 yield dut.bus.cti.eq(CycleType.END_OF_BURST if i == count-1 else CycleType.INCR_BURST)
54 yield dut.bus.cyc.eq(0)
55 yield dut.bus.stb.eq(0)
56 return data
57
58 def test_bus(self):
59 dut = SRAMPeripheral(size=16, data_width=32, granularity=8)
60 self.assertEqual(dut.bus.addr_width, 2)
61 self.assertEqual(dut.bus.data_width, 32)
62 self.assertEqual(dut.bus.granularity, 8)
63
64 def test_invalid_size(self):
65 with self.assertRaisesRegex(ValueError,
66 r"Size must be an integer power of two, not 'foo'"):
67 dut = SRAMPeripheral(size='foo')
68 with self.assertRaisesRegex(ValueError,
69 r"Size must be an integer power of two, not 3"):
70 dut = SRAMPeripheral(size=3)
71
72 def test_invalid_size_ratio(self):
73 with self.assertRaisesRegex(ValueError,
74 r"Size 2 cannot be lesser than the data width/granularity ratio of "
75 r"4 \(32 / 8\)"):
76 dut = SRAMPeripheral(size=2, data_width=32, granularity=8)
77
78 def test_read(self):
79 dut = SRAMPeripheral(size=4, data_width=8, writable=False)
80 dut.init = [0x00, 0x01, 0x02, 0x03]
81 def process():
82 for i in range(4):
83 data = (yield from wb_read(dut.bus, addr=i, sel=1))
84 self.assertEqual(data, dut.init[i])
85 yield
86 simulation_test(dut, process)
87
88 def test_read_incr_linear(self):
89 dut = SRAMPeripheral(size=8, data_width=8, writable=False)
90 dut.init = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
91 def process():
92 data = (yield from self.read_incr(dut, addr=0x00, count=6))
93 self.assertEqual(data, dut.init[:6])
94 yield
95 data = (yield from self.read_incr(dut, addr=0x06, count=2))
96 self.assertEqual(data, dut.init[6:])
97 simulation_test(dut, process)
98
99 def test_read_incr_wrap_4(self):
100 dut = SRAMPeripheral(size=8, data_width=8, writable=False)
101 dut.init = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
102 def process():
103 data = (yield from self.read_incr(dut, addr=0x01, count=8, wrap=4))
104 self.assertEqual(data, 2*(dut.init[1:4] + [dut.init[0]]))
105 simulation_test(dut, process)
106
107 def test_read_incr_wrap_8(self):
108 dut = SRAMPeripheral(size=8, data_width=8, writable=False)
109 dut.init = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
110 def process():
111 data = (yield from self.read_incr(dut, addr=0x06, count=16, wrap=8))
112 self.assertEqual(data, 2*(dut.init[6:] + dut.init[:6]))
113 simulation_test(dut, process)
114
115 def test_read_incr_wrap_16(self):
116 dut = SRAMPeripheral(size=16, data_width=8, writable=False)
117 dut.init = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
118 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
119 def process():
120 data = (yield from self.read_incr(dut, addr=0x06, count=32, wrap=16))
121 self.assertEqual(data, 2*(dut.init[6:] + dut.init[:6]))
122 simulation_test(dut, process)
123
124 def test_write(self):
125 dut = SRAMPeripheral(size=4, data_width=8)
126 def process():
127 data = [0x00, 0x01, 0x02, 0x03]
128 for i in range(len(data)):
129 yield from wb_write(dut.bus, addr=i, data=data[i], sel=1)
130 yield
131 for i in range(len(data)):
132 b = yield from wb_read(dut.bus, addr=i, sel=1)
133 yield
134 self.assertEqual(b, data[i])
135 simulation_test(dut, process)
136
137 def test_write_sel(self):
138 dut = SRAMPeripheral(size=4, data_width=16, granularity=8)
139 def process():
140 yield from wb_write(dut.bus, addr=0x0, data=0x5aa5, sel=0b01)
141 yield
142 yield from wb_write(dut.bus, addr=0x1, data=0x5aa5, sel=0b10)
143 yield
144 self.assertEqual((yield from wb_read(dut.bus, addr=0x0, sel=1)), 0x00a5)
145 yield
146 self.assertEqual((yield from wb_read(dut.bus, addr=0x1, sel=1)), 0x5a00)
147 simulation_test(dut, process)
148
149 # TODO test write bursts