3 from nmigen
.hdl
.rec
import Layout
4 from nmigen
.back
.pysim
import *
6 from ..csr
.bus
import *
9 class ElementTestCase(unittest
.TestCase
):
10 def test_layout_1_ro(self
):
11 elem
= Element(1, "r")
12 self
.assertEqual(elem
.width
, 1)
13 self
.assertEqual(elem
.access
, Element
.Access
.R
)
14 self
.assertEqual(elem
.layout
, Layout
.cast([
19 def test_layout_8_rw(self
):
20 elem
= Element(8, access
="rw")
21 self
.assertEqual(elem
.width
, 8)
22 self
.assertEqual(elem
.access
, Element
.Access
.RW
)
23 self
.assertEqual(elem
.layout
, Layout
.cast([
30 def test_layout_10_wo(self
):
31 elem
= Element(10, "w")
32 self
.assertEqual(elem
.width
, 10)
33 self
.assertEqual(elem
.access
, Element
.Access
.W
)
34 self
.assertEqual(elem
.layout
, Layout
.cast([
39 def test_layout_0_rw(self
): # degenerate but legal case
40 elem
= Element(0, access
=Element
.Access
.RW
)
41 self
.assertEqual(elem
.width
, 0)
42 self
.assertEqual(elem
.access
, Element
.Access
.RW
)
43 self
.assertEqual(elem
.layout
, Layout
.cast([
50 def test_width_wrong(self
):
51 with self
.assertRaisesRegex(ValueError,
52 r
"Width must be a non-negative integer, not -1"):
55 def test_access_wrong(self
):
56 with self
.assertRaisesRegex(ValueError,
57 r
"Access mode must be one of \"r
\", \"w
\", or \"rw
\", not 'wo'"):
61 class InterfaceTestCase(unittest.TestCase):
62 def test_layout(self):
63 iface = Interface(addr_width=12, data_width=8)
64 self.assertEqual(iface.addr_width, 12)
65 self.assertEqual(iface.data_width, 8)
66 self.assertEqual(iface.layout, Layout.cast([
74 def test_wrong_addr_width(self):
75 with self.assertRaisesRegex(ValueError,
76 r"Address width must be a positive integer
, not -1"):
77 Interface(addr_width=-1, data_width=8)
79 def test_wrong_data_width(self):
80 with self.assertRaisesRegex(ValueError,
81 r"Data width must be a positive integer
, not -1"):
82 Interface(addr_width=16, data_width=-1)
85 class MultiplexerTestCase(unittest.TestCase):
87 self.dut = Multiplexer(addr_width=16, data_width=8)
88 Fragment.get(self.dut, platform=None) # silence UnusedElaboratable
90 def test_add_4b(self):
91 self.assertEqual(self.dut.add(Element(4, "rw
")),
94 def test_add_8b(self):
95 self.assertEqual(self.dut.add(Element(8, "rw
")),
98 def test_add_12b(self):
99 self.assertEqual(self.dut.add(Element(12, "rw
")),
102 def test_add_16b(self):
103 self.assertEqual(self.dut.add(Element(16, "rw
")),
106 def test_add_two(self):
107 self.assertEqual(self.dut.add(Element(16, "rw
")),
109 self.assertEqual(self.dut.add(Element(8, "rw
")),
112 def test_add_wrong(self):
113 with self.assertRaisesRegex(TypeError,
114 r"Element must be an instance of csr\
.Element
, not 'foo'"):
117 def test_align_to(self):
118 self.assertEqual(self.dut.add(Element(8, "rw
")),
120 self.assertEqual(self.dut.align_to(2), 4)
121 self.assertEqual(self.dut.add(Element(8, "rw
")),
127 elem_4_r = Element(4, "r
")
128 self.dut.add(elem_4_r)
129 elem_8_w = Element(8, "w
")
130 self.dut.add(elem_8_w)
131 elem_16_rw = Element(16, "rw
")
132 self.dut.add(elem_16_rw)
135 yield elem_4_r.r_data.eq(0xa)
136 yield elem_16_rw.r_data.eq(0x5aa5)
139 yield bus.r_stb.eq(1)
141 yield bus.r_stb.eq(0)
142 self.assertEqual((yield elem_4_r.r_stb), 1)
143 self.assertEqual((yield elem_16_rw.r_stb), 0)
145 self.assertEqual((yield bus.r_data), 0xa)
148 yield bus.r_stb.eq(1)
150 yield bus.r_stb.eq(0)
151 self.assertEqual((yield elem_4_r.r_stb), 0)
152 self.assertEqual((yield elem_16_rw.r_stb), 1)
154 yield bus.addr.eq(3) # pipeline a read
155 self.assertEqual((yield bus.r_data), 0xa5)
157 yield bus.r_stb.eq(1)
159 yield bus.r_stb.eq(0)
160 self.assertEqual((yield elem_4_r.r_stb), 0)
161 self.assertEqual((yield elem_16_rw.r_stb), 0)
163 self.assertEqual((yield bus.r_data), 0x5a)
166 yield bus.w_data.eq(0x3d)
167 yield bus.w_stb.eq(1)
169 yield bus.w_stb.eq(0)
170 yield bus.addr.eq(2) # change address
172 self.assertEqual((yield elem_8_w.w_stb), 1)
173 self.assertEqual((yield elem_8_w.w_data), 0x3d)
174 self.assertEqual((yield elem_16_rw.w_stb), 0)
176 self.assertEqual((yield elem_8_w.w_stb), 0)
179 yield bus.w_data.eq(0x55)
180 yield bus.w_stb.eq(1)
182 self.assertEqual((yield elem_8_w.w_stb), 0)
183 self.assertEqual((yield elem_16_rw.w_stb), 0)
184 yield bus.addr.eq(3) # pipeline a write
185 yield bus.w_data.eq(0xaa)
187 self.assertEqual((yield elem_8_w.w_stb), 0)
188 self.assertEqual((yield elem_16_rw.w_stb), 0)
189 yield bus.w_stb.eq(0)
191 self.assertEqual((yield elem_8_w.w_stb), 0)
192 self.assertEqual((yield elem_16_rw.w_stb), 1)
193 self.assertEqual((yield elem_16_rw.w_data), 0xaa55)
195 with Simulator(self.dut, vcd_file=open("test
.vcd
", "w
")) as sim:
197 sim.add_sync_process(sim_test())
201 class MultiplexerAlignedTestCase(unittest.TestCase):
203 self.dut = Multiplexer(addr_width=16, data_width=8, alignment=2)
204 Fragment.get(self.dut, platform=None) # silence UnusedElaboratable
206 def test_add_two(self):
207 self.assertEqual(self.dut.add(Element(8, "rw
")),
209 self.assertEqual(self.dut.add(Element(16, "rw
")),
212 def test_over_align_to(self):
213 self.assertEqual(self.dut.add(Element(8, "rw
")),
215 self.assertEqual(self.dut.align_to(3), 8)
216 self.assertEqual(self.dut.add(Element(8, "rw
")),
219 def test_under_align_to(self):
220 self.assertEqual(self.dut.add(Element(8, "rw
")),
222 self.assertEqual(self.dut.align_to(1), 4)
223 self.assertEqual(self.dut.add(Element(8, "rw
")),
229 elem_20_rw = Element(20, "rw
")
230 self.dut.add(elem_20_rw)
233 yield bus.w_stb.eq(1)
235 yield bus.w_data.eq(0x55)
237 self.assertEqual((yield elem_20_rw.w_stb), 0)
239 yield bus.w_data.eq(0xaa)
241 self.assertEqual((yield elem_20_rw.w_stb), 0)
243 yield bus.w_data.eq(0x33)
245 self.assertEqual((yield elem_20_rw.w_stb), 0)
247 yield bus.w_data.eq(0xdd)
249 self.assertEqual((yield elem_20_rw.w_stb), 0)
250 yield bus.w_stb.eq(0)
252 self.assertEqual((yield elem_20_rw.w_stb), 1)
253 self.assertEqual((yield elem_20_rw.w_data), 0x3aa55)
255 with Simulator(self.dut, vcd_file=open("test
.vcd
", "w
")) as sim:
257 sim.add_sync_process(sim_test())
261 class DecoderTestCase(unittest.TestCase):
263 self.dut = Decoder(addr_width=16, data_width=8)
264 Fragment.get(self.dut, platform=None) # silence UnusedElaboratable
266 def test_align_to(self):
267 self.assertEqual(self.dut.add(Interface(addr_width=10, data_width=8)),
269 self.assertEqual(self.dut.align_to(12), 0x1000)
270 self.assertEqual(self.dut.add(Interface(addr_width=10, data_width=8)),
273 def test_add_wrong_sub_bus(self):
274 with self.assertRaisesRegex(TypeError,
275 r"Subordinate bus must be an instance of csr\
.Interface
, not 1"):
278 def test_add_wrong_data_width(self):
279 mux = Multiplexer(addr_width=10, data_width=16)
280 Fragment.get(mux, platform=None) # silence UnusedElaboratable
282 with self.assertRaisesRegex(ValueError,
283 r"Subordinate bus has data width
16, which
is not the same
as "
284 r"multiplexer data width
8"):
285 self.dut.add(mux.bus)
288 mux_1 = Multiplexer(addr_width=10, data_width=8)
289 self.dut.add(mux_1.bus)
290 elem_1 = Element(8, "rw
")
293 mux_2 = Multiplexer(addr_width=10, data_width=8)
294 self.dut.add(mux_2.bus)
295 elem_2 = Element(8, "rw
")
296 mux_2.add(elem_2, addr=2)
298 elem_1_addr, _, _ = self.dut.bus.memory_map.find_resource(elem_1)
299 elem_2_addr, _, _ = self.dut.bus.memory_map.find_resource(elem_2)
300 self.assertEqual(elem_1_addr, 0x0000)
301 self.assertEqual(elem_2_addr, 0x0402)
306 yield bus.addr.eq(elem_1_addr)
307 yield bus.w_stb.eq(1)
308 yield bus.w_data.eq(0x55)
310 yield bus.w_stb.eq(0)
312 self.assertEqual((yield elem_1.w_data), 0x55)
314 yield bus.addr.eq(elem_2_addr)
315 yield bus.w_stb.eq(1)
316 yield bus.w_data.eq(0xaa)
318 yield bus.w_stb.eq(0)
320 self.assertEqual((yield elem_2.w_data), 0xaa)
322 yield elem_1.r_data.eq(0x55)
323 yield elem_2.r_data.eq(0xaa)
325 yield bus.addr.eq(elem_1_addr)
326 yield bus.r_stb.eq(1)
328 yield bus.addr.eq(elem_2_addr)
330 self.assertEqual((yield bus.r_data), 0x55)
332 self.assertEqual((yield bus.r_data), 0xaa)
335 m.submodules += self.dut, mux_1, mux_2
336 with Simulator(m, vcd_file=open("test
.vcd
", "w
")) as sim:
338 sim.add_sync_process(sim_test())