test: move to sim = Simulator(dut) instead of context manager.
[lambdasoc.git] / lambdasoc / test / test_periph_base.py
1 # nmigen: UnusedElaboratable=no
2
3 import unittest
4 from nmigen import *
5 from nmigen.back.pysim import *
6
7 from ._wishbone import *
8 from ..periph.base import Peripheral, CSRBank, PeripheralBridge
9
10
11 def simulation_test(dut, process):
12 sim = Simulator(dut)
13 sim.add_clock(1e-6)
14 sim.add_sync_process(process)
15 with sim.write_vcd("test.vcd"):
16 sim.run()
17
18
19 class PeripheralTestCase(unittest.TestCase):
20 def test_name(self):
21 class Wrapper(Peripheral):
22 def __init__(self):
23 super().__init__()
24 periph_0 = Wrapper()
25 periph_1 = Peripheral(name="periph_1")
26 self.assertEqual(periph_0.name, "periph_0")
27 self.assertEqual(periph_1.name, "periph_1")
28
29 def test_periph_name_wrong(self):
30 with self.assertRaisesRegex(TypeError,
31 r"Name must be a string, not 2"):
32 periph = Peripheral(name=2)
33
34 def test_set_bus_wrong(self):
35 periph = Peripheral(src_loc_at=0)
36 with self.assertRaisesRegex(TypeError,
37 r"Bus interface must be an instance of wishbone.Interface, not 'foo'"):
38 periph.bus = "foo"
39
40 def test_get_bus_wrong(self):
41 periph = Peripheral(src_loc_at=0)
42 with self.assertRaisesRegex(NotImplementedError,
43 r"Peripheral <.*> does not have a bus interface"):
44 periph.bus
45
46 def test_set_irq_wrong(self):
47 periph = Peripheral(src_loc_at=0)
48 with self.assertRaisesRegex(TypeError,
49 r"IRQ line must be an instance of IRQLine, not 'foo'"):
50 periph.irq = "foo"
51
52 def test_get_irq_wrong(self):
53 periph = Peripheral(src_loc_at=0)
54 with self.assertRaisesRegex(NotImplementedError,
55 r"Peripheral <.*> does not have an IRQ line"):
56 periph.irq
57
58 def test_iter_csr_banks(self):
59 periph = Peripheral(src_loc_at=0)
60 bank_0 = periph.csr_bank()
61 bank_1 = periph.csr_bank(addr=0x4, alignment=2)
62 self.assertEqual(list(periph.iter_csr_banks()), [
63 (bank_0, None, None),
64 (bank_1, 0x4, 2),
65 ])
66
67 def test_iter_windows(self):
68 periph = Peripheral(src_loc_at=0)
69 win_0 = periph.window(addr_width=2, data_width=8)
70 win_1 = periph.window(addr_width=4, data_width=8, addr=0x4, sparse=True)
71 self.assertEqual(list(periph.iter_windows()), [
72 (win_0, None, None),
73 (win_1, 0x4, True),
74 ])
75
76 def test_iter_events(self):
77 periph = Peripheral(src_loc_at=0)
78 ev_0 = periph.event()
79 ev_1 = periph.event(mode="rise")
80 self.assertEqual((ev_0.name, ev_0.mode), ("ev_0", "level"))
81 self.assertEqual((ev_1.name, ev_1.mode), ("ev_1", "rise"))
82 self.assertEqual(list(periph.iter_events()), [
83 ev_0,
84 ev_1,
85 ])
86
87
88 class CSRBankTestCase(unittest.TestCase):
89 def test_csr_name(self):
90 bank = CSRBank(name_prefix="foo")
91 bar = bank.csr(1, "r")
92 self.assertEqual(bar.name, "foo_bar")
93
94 def test_csr_name_wrong(self):
95 bank = CSRBank()
96 with self.assertRaisesRegex(TypeError,
97 r"Name must be a string, not 2"):
98 bank.csr(1, "r", name=2)
99
100 def test_iter_csr_regs(self):
101 bank = CSRBank()
102 csr_0 = bank.csr(1, "r")
103 csr_1 = bank.csr(8, "rw", addr=0x4, alignment=2)
104 self.assertEqual(list(bank.iter_csr_regs()), [
105 (csr_0, None, None),
106 (csr_1, 0x4, 2),
107 ])
108
109
110 class PeripheralBridgeTestCase(unittest.TestCase):
111 def test_periph_wrong(self):
112 with self.assertRaisesRegex(TypeError,
113 r"Peripheral must be an instance of Peripheral, not 'foo'"):
114 PeripheralBridge('foo', data_width=8, granularity=8, features=(), alignment=0)
115
116
117 class PeripheralSimulationTestCase(unittest.TestCase):
118 def test_csrs(self):
119 class DummyPeripheral(Peripheral, Elaboratable):
120 def __init__(self):
121 super().__init__()
122 bank = self.csr_bank(addr=0x100)
123 self._csr_0 = bank.csr(8, "r")
124 self._csr_1 = bank.csr(8, "r", addr=0x8, alignment=4)
125 self._csr_2 = bank.csr(8, "rw")
126
127 self.win_0 = self.window(addr_width=1, data_width=8, sparse=True, addr=0x000)
128 self.win_1 = self.window(addr_width=1, data_width=32, granularity=8, addr=0x200)
129
130 self._bridge = self.bridge(data_width=32, granularity=8, alignment=2)
131 self.bus = self._bridge.bus
132
133 def elaborate(self, platform):
134 m = Module()
135 m.submodules.bridge = self._bridge
136 m.d.comb += [
137 self._csr_0.r_data.eq(0xa),
138 self._csr_1.r_data.eq(0xb),
139 ]
140 with m.If(self._csr_2.w_stb):
141 m.d.sync += self._csr_2.r_data.eq(self._csr_2.w_data)
142 return m
143
144 dut = DummyPeripheral()
145
146 def process():
147 self.assertEqual((yield from wb_read(dut.bus, addr=0x100 >> 2, sel=0xf)), 0xa)
148 yield
149 self.assertEqual((yield from wb_read(dut.bus, addr=0x108 >> 2, sel=0xf)), 0xb)
150 yield
151 yield from wb_write(dut.bus, addr=0x118 >> 2, data=0xc, sel=0xf)
152 yield
153 self.assertEqual((yield from wb_read(dut.bus, addr=0x118 >> 2, sel=0xf)), 0xc)
154 yield
155
156 yield dut.bus.cyc.eq(1)
157 yield dut.bus.adr.eq(0x000 >> 2)
158 yield Delay(1e-7)
159 self.assertEqual((yield dut.win_0.cyc), 1)
160
161 yield dut.bus.adr.eq(0x200 >> 2)
162 yield Delay(1e-7)
163 self.assertEqual((yield dut.win_1.cyc), 1)
164
165 simulation_test(dut, process)
166
167 def test_events(self):
168 class DummyPeripheral(Peripheral, Elaboratable):
169 def __init__(self):
170 super().__init__()
171 self.ev_0 = self.event()
172 self.ev_1 = self.event(mode="rise")
173 self.ev_2 = self.event(mode="fall")
174 self._bridge = self.bridge(data_width=8)
175 self.bus = self._bridge.bus
176 self.irq = self._bridge.irq
177
178 def elaborate(self, platform):
179 m = Module()
180 m.submodules.bridge = self._bridge
181 return m
182
183 dut = DummyPeripheral()
184
185 ev_status_addr = 0x0
186 ev_pending_addr = 0x1
187 ev_enable_addr = 0x2
188
189 def process():
190 yield dut.ev_0.stb.eq(1)
191 yield dut.ev_1.stb.eq(0)
192 yield dut.ev_2.stb.eq(1)
193 yield
194 self.assertEqual((yield dut.irq), 0)
195 self.assertEqual((yield from wb_read(dut.bus, ev_status_addr, sel=0xf)), 0b101)
196 yield
197
198 yield from wb_write(dut.bus, ev_enable_addr, data=0b111, sel=0xf)
199 yield
200 self.assertEqual((yield dut.irq), 1)
201
202 yield from wb_write(dut.bus, ev_pending_addr, data=0b001, sel=0xf)
203 yield
204 self.assertEqual((yield from wb_read(dut.bus, ev_pending_addr, sel=0xf)), 0b001)
205 yield
206 self.assertEqual((yield dut.irq), 1)
207 yield dut.ev_0.stb.eq(0)
208 yield from wb_write(dut.bus, ev_pending_addr, data=0b001, sel=0xf)
209 yield
210 self.assertEqual((yield dut.irq), 0)
211
212 yield dut.ev_1.stb.eq(1)
213 yield
214 self.assertEqual((yield from wb_read(dut.bus, ev_pending_addr, sel=0xf)), 0b010)
215 yield
216 self.assertEqual((yield dut.irq), 1)
217 yield from wb_write(dut.bus, ev_pending_addr, data=0b010, sel=0xf)
218 yield
219 self.assertEqual((yield dut.irq), 0)
220
221 yield dut.ev_2.stb.eq(0)
222 yield
223 self.assertEqual((yield from wb_read(dut.bus, ev_pending_addr, sel=0xf)), 0b100)
224 yield
225 self.assertEqual((yield dut.irq), 1)
226 yield from wb_write(dut.bus, ev_pending_addr, data=0b100, sel=0xf)
227 yield
228 self.assertEqual((yield dut.irq), 0)
229
230 simulation_test(dut, process)