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