1 # nmigen: UnusedElaboratable=no
5 from nmigen
.back
.pysim
import *
7 from nmigen_soc
.memory
import MemoryMap
9 from .utils
.wishbone
import *
10 from ..periph
.base
import Peripheral
, CSRBank
, PeripheralBridge
13 def simulation_test(dut
, process
):
16 sim
.add_sync_process(process
)
17 with sim
.write_vcd("test.vcd"):
21 class PeripheralTestCase(unittest
.TestCase
):
23 class Wrapper(Peripheral
):
27 periph_1
= Peripheral(name
="periph_1")
28 self
.assertEqual(periph_0
.name
, "periph_0")
29 self
.assertEqual(periph_1
.name
, "periph_1")
31 def test_periph_name_wrong(self
):
32 with self
.assertRaisesRegex(TypeError,
33 r
"Name must be a string, not 2"):
34 periph
= Peripheral(name
=2)
36 def test_set_bus_wrong(self
):
37 periph
= Peripheral(src_loc_at
=0)
38 with self
.assertRaisesRegex(TypeError,
39 r
"Bus interface must be an instance of wishbone.Interface, not 'foo'"):
42 def test_get_bus_wrong(self
):
43 periph
= Peripheral(src_loc_at
=0)
44 with self
.assertRaisesRegex(NotImplementedError,
45 r
"Peripheral <.*> does not have a bus interface"):
48 def test_set_irq_wrong(self
):
49 periph
= Peripheral(src_loc_at
=0)
50 with self
.assertRaisesRegex(TypeError,
51 r
"IRQ line must be an instance of IRQLine, not 'foo'"):
54 def test_get_irq_wrong(self
):
55 periph
= Peripheral(src_loc_at
=0)
56 with self
.assertRaisesRegex(NotImplementedError,
57 r
"Peripheral <.*> does not have an IRQ line"):
60 def test_iter_csr_banks(self
):
61 periph
= Peripheral(src_loc_at
=0)
62 bank_0
= periph
.csr_bank()
63 bank_1
= periph
.csr_bank(addr
=0x4, alignment
=2)
64 self
.assertEqual(list(periph
.iter_csr_banks()), [
69 def test_iter_windows(self
):
70 periph
= Peripheral(src_loc_at
=0)
71 win_0
= periph
.window(addr_width
=2, data_width
=8)
72 win_1
= periph
.window(addr_width
=4, data_width
=8, addr
=0x4, sparse
=True)
73 self
.assertEqual(list(periph
.iter_windows()), [
78 def test_iter_events(self
):
79 periph
= Peripheral(src_loc_at
=0)
81 ev_1
= periph
.event(mode
="rise")
82 self
.assertEqual((ev_0
.name
, ev_0
.mode
), ("ev_0", "level"))
83 self
.assertEqual((ev_1
.name
, ev_1
.mode
), ("ev_1", "rise"))
84 self
.assertEqual(list(periph
.iter_events()), [
90 class CSRBankTestCase(unittest
.TestCase
):
91 def test_bank_name(self
):
92 bank
= CSRBank(name
="foo")
93 self
.assertEqual(bank
.name
, "foo")
95 def test_bank_name_wrong(self
):
96 with self
.assertRaisesRegex(TypeError,
97 r
"Name must be a string, not 2"):
98 bank
= CSRBank(name
=2)
100 def test_csr_name_wrong(self
):
102 with self
.assertRaisesRegex(TypeError,
103 r
"Name must be a string, not 2"):
104 bank
.csr(1, "r", name
=2)
106 def test_iter_csr_regs(self
):
108 csr_0
= bank
.csr(1, "r")
109 csr_1
= bank
.csr(8, "rw", addr
=0x4, alignment
=2)
110 self
.assertEqual(list(bank
.iter_csr_regs()), [
116 class PeripheralBridgeTestCase(unittest
.TestCase
):
117 def test_periph_wrong(self
):
118 with self
.assertRaisesRegex(TypeError,
119 r
"Peripheral must be an instance of Peripheral, not 'foo'"):
120 PeripheralBridge('foo', data_width
=8, granularity
=8, features
=(), alignment
=0)
123 class PeripheralSimulationTestCase(unittest
.TestCase
):
125 class DummyPeripheral(Peripheral
, Elaboratable
):
128 bank
= self
.csr_bank(addr
=0x100)
129 self
._csr
_0 = bank
.csr(8, "r")
130 self
._csr
_1 = bank
.csr(8, "r", addr
=0x8, alignment
=4)
131 self
._csr
_2 = bank
.csr(8, "rw")
133 self
.win_0
= self
.window(addr_width
=1, data_width
=8, sparse
=True, addr
=0x000)
134 self
.win_1
= self
.window(addr_width
=1, data_width
=32, granularity
=8, addr
=0x200)
135 self
.win_0
.memory_map
= MemoryMap(addr_width
=1, data_width
=8)
136 self
.win_1
.memory_map
= MemoryMap(addr_width
=3, data_width
=8)
138 self
._bridge
= self
.bridge(data_width
=32, granularity
=8, alignment
=2)
139 self
.bus
= self
._bridge
.bus
141 def elaborate(self
, platform
):
143 m
.submodules
.bridge
= self
._bridge
145 self
._csr
_0.r_data
.eq(0xa),
146 self
._csr
_1.r_data
.eq(0xb),
148 with m
.If(self
._csr
_2.w_stb
):
149 m
.d
.sync
+= self
._csr
_2.r_data
.eq(self
._csr
_2.w_data
)
152 dut
= DummyPeripheral()
155 self
.assertEqual((yield from wb_read(dut
.bus
, addr
=0x100 >> 2, sel
=0xf)), 0xa)
157 self
.assertEqual((yield from wb_read(dut
.bus
, addr
=0x108 >> 2, sel
=0xf)), 0xb)
159 yield from wb_write(dut
.bus
, addr
=0x118 >> 2, data
=0xc, sel
=0xf)
161 self
.assertEqual((yield from wb_read(dut
.bus
, addr
=0x118 >> 2, sel
=0xf)), 0xc)
164 yield dut
.bus
.cyc
.eq(1)
165 yield dut
.bus
.adr
.eq(0x000 >> 2)
167 self
.assertEqual((yield dut
.win_0
.cyc
), 1)
169 yield dut
.bus
.adr
.eq(0x200 >> 2)
171 self
.assertEqual((yield dut
.win_1
.cyc
), 1)
173 simulation_test(dut
, process
)
175 def test_events(self
):
176 class DummyPeripheral(Peripheral
, Elaboratable
):
179 self
.ev_0
= self
.event()
180 self
.ev_1
= self
.event(mode
="rise")
181 self
.ev_2
= self
.event(mode
="fall")
182 self
._bridge
= self
.bridge(data_width
=8)
183 self
.bus
= self
._bridge
.bus
184 self
.irq
= self
._bridge
.irq
186 def elaborate(self
, platform
):
188 m
.submodules
.bridge
= self
._bridge
191 dut
= DummyPeripheral()
194 ev_pending_addr
= 0x1
198 yield dut
.ev_0
.stb
.eq(1)
199 yield dut
.ev_1
.stb
.eq(0)
200 yield dut
.ev_2
.stb
.eq(1)
202 self
.assertEqual((yield dut
.irq
), 0)
203 self
.assertEqual((yield from wb_read(dut
.bus
, ev_status_addr
, sel
=0xf)), 0b101)
206 yield from wb_write(dut
.bus
, ev_enable_addr
, data
=0b111, sel
=0xf)
208 self
.assertEqual((yield dut
.irq
), 1)
210 yield from wb_write(dut
.bus
, ev_pending_addr
, data
=0b001, sel
=0xf)
212 self
.assertEqual((yield from wb_read(dut
.bus
, ev_pending_addr
, sel
=0xf)), 0b001)
214 self
.assertEqual((yield dut
.irq
), 1)
215 yield dut
.ev_0
.stb
.eq(0)
216 yield from wb_write(dut
.bus
, ev_pending_addr
, data
=0b001, sel
=0xf)
218 self
.assertEqual((yield dut
.irq
), 0)
220 yield dut
.ev_1
.stb
.eq(1)
222 self
.assertEqual((yield from wb_read(dut
.bus
, ev_pending_addr
, sel
=0xf)), 0b010)
224 self
.assertEqual((yield dut
.irq
), 1)
225 yield from wb_write(dut
.bus
, ev_pending_addr
, data
=0b010, sel
=0xf)
227 self
.assertEqual((yield dut
.irq
), 0)
229 yield dut
.ev_2
.stb
.eq(0)
231 self
.assertEqual((yield from wb_read(dut
.bus
, ev_pending_addr
, sel
=0xf)), 0b100)
233 self
.assertEqual((yield dut
.irq
), 1)
234 yield from wb_write(dut
.bus
, ev_pending_addr
, data
=0b100, sel
=0xf)
236 self
.assertEqual((yield dut
.irq
), 0)
238 simulation_test(dut
, process
)