1 # nmigen: UnusedElaboratable=no
5 from nmigen
.hdl
.rec
import *
6 from nmigen
.back
.pysim
import *
8 from ..wishbone
.bus
import *
11 class InterfaceTestCase(unittest
.TestCase
):
12 def test_simple(self
):
13 iface
= Interface(addr_width
=32, data_width
=8)
14 self
.assertEqual(iface
.addr_width
, 32)
15 self
.assertEqual(iface
.data_width
, 8)
16 self
.assertEqual(iface
.granularity
, 8)
17 self
.assertEqual(iface
.memory_map
.addr_width
, 32)
18 self
.assertEqual(iface
.memory_map
.data_width
, 8)
19 self
.assertEqual(iface
.layout
, Layout
.cast([
20 ("adr", 32, DIR_FANOUT
),
21 ("dat_w", 8, DIR_FANOUT
),
22 ("dat_r", 8, DIR_FANIN
),
23 ("sel", 1, DIR_FANOUT
),
24 ("cyc", 1, DIR_FANOUT
),
25 ("stb", 1, DIR_FANOUT
),
26 ("we", 1, DIR_FANOUT
),
27 ("ack", 1, DIR_FANIN
),
30 def test_granularity(self
):
31 iface
= Interface(addr_width
=30, data_width
=32, granularity
=8)
32 self
.assertEqual(iface
.addr_width
, 30)
33 self
.assertEqual(iface
.data_width
, 32)
34 self
.assertEqual(iface
.granularity
, 8)
35 self
.assertEqual(iface
.memory_map
.addr_width
, 32)
36 self
.assertEqual(iface
.memory_map
.data_width
, 8)
37 self
.assertEqual(iface
.layout
, Layout
.cast([
38 ("adr", 30, DIR_FANOUT
),
39 ("dat_w", 32, DIR_FANOUT
),
40 ("dat_r", 32, DIR_FANIN
),
41 ("sel", 4, DIR_FANOUT
),
42 ("cyc", 1, DIR_FANOUT
),
43 ("stb", 1, DIR_FANOUT
),
44 ("we", 1, DIR_FANOUT
),
45 ("ack", 1, DIR_FANIN
),
48 def test_features(self
):
49 iface
= Interface(addr_width
=32, data_width
=32,
50 features
={"rty", "err", "stall", "lock", "cti", "bte"})
51 self
.assertEqual(iface
.layout
, Layout
.cast([
52 ("adr", 32, DIR_FANOUT
),
53 ("dat_w", 32, DIR_FANOUT
),
54 ("dat_r", 32, DIR_FANIN
),
55 ("sel", 1, DIR_FANOUT
),
56 ("cyc", 1, DIR_FANOUT
),
57 ("stb", 1, DIR_FANOUT
),
58 ("we", 1, DIR_FANOUT
),
59 ("ack", 1, DIR_FANIN
),
60 ("err", 1, DIR_FANIN
),
61 ("rty", 1, DIR_FANIN
),
62 ("stall", 1, DIR_FANIN
),
63 ("lock", 1, DIR_FANOUT
),
64 ("cti", CycleType
, DIR_FANOUT
),
65 ("bte", BurstTypeExt
, DIR_FANOUT
),
68 def test_wrong_addr_width(self
):
69 with self
.assertRaisesRegex(ValueError,
70 r
"Address width must be a non-negative integer, not -1"):
71 Interface(addr_width
=-1, data_width
=8)
73 def test_wrong_data_width(self
):
74 with self
.assertRaisesRegex(ValueError,
75 r
"Data width must be one of 8, 16, 32, 64, not 7"):
76 Interface(addr_width
=0, data_width
=7)
78 def test_wrong_granularity(self
):
79 with self
.assertRaisesRegex(ValueError,
80 r
"Granularity must be one of 8, 16, 32, 64, not 7"):
81 Interface(addr_width
=0, data_width
=32, granularity
=7)
83 def test_wrong_granularity_wide(self
):
84 with self
.assertRaisesRegex(ValueError,
85 r
"Granularity 32 may not be greater than data width 8"):
86 Interface(addr_width
=0, data_width
=8, granularity
=32)
88 def test_wrong_features(self
):
89 with self
.assertRaisesRegex(ValueError,
90 r
"Optional signal\(s\) 'foo' are not supported"):
91 Interface(addr_width
=0, data_width
=8, features
={"foo"})
94 class DecoderTestCase(unittest
.TestCase
):
96 self
.dut
= Decoder(addr_width
=31, data_width
=32, granularity
=16)
98 def test_add_align_to(self
):
99 sub_1
= Interface(addr_width
=15, data_width
=32, granularity
=16)
100 sub_2
= Interface(addr_width
=15, data_width
=32, granularity
=16)
101 self
.assertEqual(self
.dut
.add(sub_1
), (0x00000000, 0x00010000, 1))
102 self
.assertEqual(self
.dut
.align_to(18), 0x000040000)
103 self
.assertEqual(self
.dut
.add(sub_2
), (0x00040000, 0x00050000, 1))
105 def test_add_wrong(self
):
106 with self
.assertRaisesRegex(TypeError,
107 r
"Subordinate bus must be an instance of wishbone\.Interface, not 'foo'"):
110 def test_add_wrong_granularity(self
):
111 with self
.assertRaisesRegex(ValueError,
112 r
"Subordinate bus has granularity 32, which is greater than "
113 r
"the decoder granularity 16"):
114 self
.dut
.add(Interface(addr_width
=15, data_width
=32, granularity
=32))
116 def test_add_wrong_width_dense(self
):
117 with self
.assertRaisesRegex(ValueError,
118 r
"Subordinate bus has data width 16, which is not the same as decoder "
119 r
"data width 32 \(required for dense address translation\)"):
120 self
.dut
.add(Interface(addr_width
=15, data_width
=16, granularity
=16))
122 def test_add_wrong_granularity_sparse(self
):
123 with self
.assertRaisesRegex(ValueError,
124 r
"Subordinate bus has data width 64, which is not the same as subordinate "
125 r
"bus granularity 16 \(required for sparse address translation\)"):
126 self
.dut
.add(Interface(addr_width
=15, data_width
=64, granularity
=16), sparse
=True)
128 def test_add_wrong_optional_output(self
):
129 with self
.assertRaisesRegex(ValueError,
130 r
"Subordinate bus has optional output 'err', but the decoder does "
131 r
"not have a corresponding input"):
132 self
.dut
.add(Interface(addr_width
=15, data_width
=32, granularity
=16, features
={"err"}))
135 class DecoderSimulationTestCase(unittest
.TestCase
):
136 def test_simple(self
):
137 dut
= Decoder(addr_width
=30, data_width
=32, granularity
=8,
138 features
={"err", "rty", "stall", "lock", "cti", "bte"})
139 sub_1
= Interface(addr_width
=14, data_width
=32, granularity
=8)
140 dut
.add(sub_1
, addr
=0x10000)
141 sub_2
= Interface(addr_width
=14, data_width
=32, granularity
=8,
142 features
={"err", "rty", "stall", "lock", "cti", "bte"})
146 yield dut
.bus
.adr
.eq(0x10400 >> 2)
147 yield dut
.bus
.cyc
.eq(1)
148 yield dut
.bus
.stb
.eq(1)
149 yield dut
.bus
.sel
.eq(0b11)
150 yield dut
.bus
.dat_w
.eq(0x12345678)
151 yield dut
.bus
.lock
.eq(1)
152 yield dut
.bus
.cti
.eq(CycleType
.INCR_BURST
)
153 yield dut
.bus
.bte
.eq(BurstTypeExt
.WRAP_4
)
154 yield sub_1
.ack
.eq(1)
155 yield sub_1
.dat_r
.eq(0xabcdef01)
156 yield sub_2
.dat_r
.eq(0x5678abcd)
158 self
.assertEqual((yield sub_1
.adr
), 0x400 >> 2)
159 self
.assertEqual((yield sub_1
.cyc
), 1)
160 self
.assertEqual((yield sub_2
.cyc
), 0)
161 self
.assertEqual((yield sub_1
.stb
), 1)
162 self
.assertEqual((yield sub_1
.sel
), 0b11)
163 self
.assertEqual((yield sub_1
.dat_w
), 0x12345678)
164 self
.assertEqual((yield dut
.bus
.ack
), 1)
165 self
.assertEqual((yield dut
.bus
.err
), 0)
166 self
.assertEqual((yield dut
.bus
.rty
), 0)
167 self
.assertEqual((yield dut
.bus
.dat_r
), 0xabcdef01)
169 yield dut
.bus
.adr
.eq(0x20400 >> 2)
170 yield sub_1
.ack
.eq(0)
171 yield sub_2
.err
.eq(1)
172 yield sub_2
.rty
.eq(1)
173 yield sub_2
.stall
.eq(1)
175 self
.assertEqual((yield sub_2
.adr
), 0x400 >> 2)
176 self
.assertEqual((yield sub_1
.cyc
), 0)
177 self
.assertEqual((yield sub_2
.cyc
), 1)
178 self
.assertEqual((yield sub_1
.stb
), 1)
179 self
.assertEqual((yield sub_1
.sel
), 0b11)
180 self
.assertEqual((yield sub_1
.dat_w
), 0x12345678)
181 self
.assertEqual((yield sub_2
.lock
), 1)
182 self
.assertEqual((yield sub_2
.cti
), CycleType
.INCR_BURST
.value
)
183 self
.assertEqual((yield sub_2
.bte
), BurstTypeExt
.WRAP_4
.value
)
184 self
.assertEqual((yield dut
.bus
.ack
), 0)
185 self
.assertEqual((yield dut
.bus
.err
), 1)
186 self
.assertEqual((yield dut
.bus
.rty
), 1)
187 self
.assertEqual((yield dut
.bus
.stall
), 1)
188 self
.assertEqual((yield dut
.bus
.dat_r
), 0x5678abcd)
190 with
Simulator(dut
, vcd_file
=open("test.vcd", "w")) as sim
:
191 sim
.add_process(sim_test())
194 def test_addr_translate(self
):
195 class AddressLoopback(Elaboratable
):
196 def __init__(self
, **kwargs
):
197 self
.bus
= Interface(**kwargs
)
199 def elaborate(self
, platform
):
202 for index
, sel_bit
in enumerate(self
.bus
.sel
):
204 segment
= self
.bus
.dat_r
.word_select(index
, self
.bus
.granularity
)
205 m
.d
.comb
+= segment
.eq(self
.bus
.adr
+ index
)
209 dut
= Decoder(addr_width
=20, data_width
=32, granularity
=16)
210 loop_1
= AddressLoopback(addr_width
=7, data_width
=32, granularity
=16)
211 self
.assertEqual(dut
.add(loop_1
.bus
, addr
=0x10000),
212 (0x10000, 0x10100, 1))
213 loop_2
= AddressLoopback(addr_width
=6, data_width
=32, granularity
=8)
214 self
.assertEqual(dut
.add(loop_2
.bus
, addr
=0x20000),
215 (0x20000, 0x20080, 2))
216 loop_3
= AddressLoopback(addr_width
=8, data_width
=16, granularity
=16)
217 self
.assertEqual(dut
.add(loop_3
.bus
, addr
=0x30000, sparse
=True),
218 (0x30000, 0x30100, 1))
219 loop_4
= AddressLoopback(addr_width
=8, data_width
=8, granularity
=8)
220 self
.assertEqual(dut
.add(loop_4
.bus
, addr
=0x40000, sparse
=True),
221 (0x40000, 0x40100, 1))
224 yield dut
.bus
.cyc
.eq(1)
226 yield dut
.bus
.adr
.eq(0x10010 >> 1)
228 yield dut
.bus
.sel
.eq(0b11)
230 self
.assertEqual((yield dut
.bus
.dat_r
), 0x00090008)
232 yield dut
.bus
.sel
.eq(0b01)
234 self
.assertEqual((yield dut
.bus
.dat_r
), 0x00000008)
236 yield dut
.bus
.sel
.eq(0b10)
238 self
.assertEqual((yield dut
.bus
.dat_r
), 0x00090000)
240 yield dut
.bus
.adr
.eq(0x20010 >> 1)
242 yield dut
.bus
.sel
.eq(0b11)
244 self
.assertEqual((yield dut
.bus
.dat_r
), 0x13121110)
246 yield dut
.bus
.sel
.eq(0b01)
248 self
.assertEqual((yield dut
.bus
.dat_r
), 0x00001110)
250 yield dut
.bus
.sel
.eq(0b10)
252 self
.assertEqual((yield dut
.bus
.dat_r
), 0x13120000)
254 yield dut
.bus
.adr
.eq(0x30010 >> 1)
256 yield dut
.bus
.sel
.eq(0b11)
258 self
.assertEqual((yield dut
.bus
.dat_r
), 0x0008)
260 yield dut
.bus
.sel
.eq(0b01)
262 self
.assertEqual((yield dut
.bus
.dat_r
), 0x0008)
264 yield dut
.bus
.sel
.eq(0b10)
266 self
.assertEqual((yield dut
.bus
.dat_r
), 0x0000)
268 yield dut
.bus
.adr
.eq(0x30012 >> 1)
270 yield dut
.bus
.sel
.eq(0b11)
272 self
.assertEqual((yield dut
.bus
.dat_r
), 0x0009)
274 yield dut
.bus
.adr
.eq(0x40010 >> 1)
276 yield dut
.bus
.sel
.eq(0b11)
278 self
.assertEqual((yield dut
.bus
.dat_r
), 0x08)
280 yield dut
.bus
.sel
.eq(0b01)
282 self
.assertEqual((yield dut
.bus
.dat_r
), 0x08)
284 yield dut
.bus
.sel
.eq(0b10)
286 self
.assertEqual((yield dut
.bus
.dat_r
), 0x00)
288 yield dut
.bus
.adr
.eq(0x40012 >> 1)
290 yield dut
.bus
.sel
.eq(0b11)
292 self
.assertEqual((yield dut
.bus
.dat_r
), 0x09)
295 m
.submodules
+= dut
, loop_1
, loop_2
, loop_3
, loop_4
296 with
Simulator(m
, vcd_file
=open("test.vcd", "w")) as sim
:
297 sim
.add_process(sim_test())