Skip to content

Commit 1c7e14f

Browse files
FatsieFatsieFS
authored andcommitted
[WIP]wishbone.Connector class
Implementation of a module that allows to connect one initiator to one subordinate.bus. Currently connecting initiator bus with data width greater than the subordinate bus is not implemented. Implementation of that feature will need to instantiate multiple subordinate bus cycles for one initiator bus cycle.
1 parent 217d4ea commit 1c7e14f

File tree

2 files changed

+381
-1
lines changed

2 files changed

+381
-1
lines changed

amaranth_soc/test/test_wishbone_bus.py

+263
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,269 @@ def test_set_map_wrong_addr_width(self):
123123
iface.memory_map = MemoryMap(addr_width=30, data_width=8)
124124

125125

126+
class ConnectorTestCase(unittest.TestCase):
127+
def test_wrong_intr(self):
128+
sub_bus = Interface(addr_width=10, data_width=8)
129+
with self.assertRaisesRegex(TypeError,
130+
r"Initiator bus must be an instance of wishbone.Interface, not 'foo'"):
131+
Connector(intr_bus="foo", sub_bus=sub_bus)
132+
133+
def test_wrong_sub(self):
134+
intr_bus = Interface(addr_width=10, data_width=8)
135+
with self.assertRaisesRegex(TypeError,
136+
r"Subordinate bus must be an instance of wishbone.Interface, not 'foo'"):
137+
Connector(intr_bus=intr_bus, sub_bus="foo")
138+
139+
def test_wrong_bitsize(self):
140+
intr_bus = Interface(addr_width=10, data_width=32)
141+
sub_bus = Interface(addr_width=10, data_width=8)
142+
with self.assertRaisesRegex(ValueError,
143+
r"Total bit size of initiator and subordinate bus have to be the same"):
144+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
145+
146+
def test_wrong_granularity(self):
147+
intr_bus = Interface(addr_width=12, data_width=8)
148+
sub_bus = Interface(addr_width=10, data_width=32)
149+
with self.assertRaisesRegex(ValueError,
150+
r"Granularity of subordinate bus has to be smaller or equal to "
151+
r"granulariy of initiator bus"):
152+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
153+
154+
def test_lock_mismatch(self):
155+
intr_bus = Interface(addr_width=10, data_width=8, features={"lock"})
156+
sub_bus = Interface(addr_width=10, data_width=8)
157+
with self.assertRaisesRegex(ValueError,
158+
r"Initiator bus has optional output 'lock', but the subordinate bus "
159+
r"does not have a corresponding input"):
160+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
161+
162+
def test_err_mismatch(self):
163+
intr_bus = Interface(addr_width=10, data_width=8)
164+
sub_bus = Interface(addr_width=10, data_width=8, features={"err"})
165+
with self.assertRaisesRegex(ValueError,
166+
r"Subordinate bus has optional output 'err', but the initiator bus "
167+
r"does not have a corresponding input"):
168+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
169+
170+
def test_rty_mismatch(self):
171+
intr_bus = Interface(addr_width=10, data_width=8)
172+
sub_bus = Interface(addr_width=10, data_width=8, features={"rty"})
173+
with self.assertRaisesRegex(ValueError,
174+
r"Subordinate bus has optional output 'rty', but the initiator bus "
175+
r"does not have a corresponding input"):
176+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
177+
178+
def test_not_implemented_multicycle(self):
179+
intr_bus = Interface(addr_width=10, data_width=32)
180+
sub_bus = Interface(addr_width=12, data_width=8)
181+
with self.assertRaisesRegex(NotImplementedError,
182+
r"Support for multi-cycle bus operation when initiator data_width is"
183+
r"bigger than the subordinate one is not implemented."):
184+
Connector(intr_bus=intr_bus, sub_bus=sub_bus)
185+
186+
187+
class ConnectorSimulationTestCase(unittest.TestCase):
188+
def test_same(self):
189+
intr_bus = Interface(addr_width=10, data_width=32, granularity=8)
190+
sub_bus = Interface(addr_width=10, data_width=32, granularity=8)
191+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
192+
193+
def sim_test():
194+
yield intr_bus.adr.eq(1)
195+
yield intr_bus.we.eq(0)
196+
yield intr_bus.cyc.eq(1)
197+
yield intr_bus.stb.eq(1)
198+
yield intr_bus.sel.eq(5)
199+
yield Delay(1e-6)
200+
self.assertEqual((yield sub_bus.adr), 1)
201+
self.assertEqual((yield sub_bus.we), 0)
202+
self.assertEqual((yield sub_bus.cyc), 1)
203+
self.assertEqual((yield sub_bus.stb), 1)
204+
self.assertEqual((yield sub_bus.sel), 5)
205+
yield sub_bus.ack.eq(1)
206+
yield Delay(1e-6)
207+
self.assertEqual((yield intr_bus.ack), 1)
208+
yield intr_bus.adr.eq(127)
209+
yield intr_bus.we.eq(1)
210+
yield intr_bus.cyc.eq(1)
211+
yield intr_bus.stb.eq(0)
212+
yield intr_bus.sel.eq(10)
213+
yield Delay(1e-6)
214+
self.assertEqual((yield sub_bus.adr), 127)
215+
self.assertEqual((yield sub_bus.we), 1)
216+
self.assertEqual((yield sub_bus.cyc), 1)
217+
self.assertEqual((yield sub_bus.stb), 0)
218+
self.assertEqual((yield sub_bus.sel), 10)
219+
220+
sim = Simulator(dut)
221+
sim.add_process(sim_test)
222+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
223+
sim.run()
224+
225+
def test_same_pipelined(self):
226+
intr_bus = Interface(addr_width=10, data_width=8, features={"stall"})
227+
sub_bus = Interface(addr_width=10, data_width=8, features={"stall"})
228+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
229+
230+
def sim_test():
231+
yield intr_bus.adr.eq(1)
232+
yield intr_bus.we.eq(0)
233+
yield intr_bus.cyc.eq(1)
234+
yield intr_bus.stb.eq(1)
235+
yield intr_bus.sel.eq(1)
236+
yield sub_bus.stall.eq(1)
237+
yield Delay(1e-6)
238+
self.assertEqual((yield sub_bus.adr), 1)
239+
self.assertEqual((yield sub_bus.we), 0)
240+
self.assertEqual((yield sub_bus.cyc), 1)
241+
self.assertEqual((yield sub_bus.stb), 1)
242+
self.assertEqual((yield sub_bus.sel), 1)
243+
self.assertEqual((yield intr_bus.stall), 1)
244+
yield sub_bus.stall.eq(0)
245+
yield Delay(1e-6)
246+
self.assertEqual((yield intr_bus.stall), 0)
247+
yield sub_bus.ack.eq(1)
248+
yield Delay(1e-6)
249+
self.assertEqual((yield intr_bus.ack), 1)
250+
251+
sim = Simulator(dut)
252+
sim.add_process(sim_test)
253+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
254+
sim.run()
255+
256+
def test_default(self):
257+
intr_bus = Interface(addr_width=10, data_width=8, features={"err", "rty"})
258+
sub_bus = Interface(addr_width=10, data_width=8, features={"lock", "cti", "bte"})
259+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
260+
261+
def sim_test():
262+
yield Delay(1e-6)
263+
self.assertEqual((yield intr_bus.err), 0)
264+
self.assertEqual((yield intr_bus.rty), 0)
265+
self.assertEqual((yield sub_bus.lock), 0)
266+
self.assertEqual((yield sub_bus.cti), CycleType.CLASSIC.value)
267+
self.assertEqual((yield sub_bus.bte), BurstTypeExt.LINEAR.value)
268+
269+
sim = Simulator(dut)
270+
sim.add_process(sim_test)
271+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
272+
sim.run()
273+
274+
def test_conv_granularity(self):
275+
intr_bus = Interface(addr_width=10, data_width=32)
276+
sub_bus = Interface(addr_width=10, data_width=32, granularity=8)
277+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
278+
279+
def sim_test():
280+
yield intr_bus.sel.eq(1)
281+
yield Delay(1e-6)
282+
self.assertEqual((yield sub_bus.sel), 0b1111)
283+
yield intr_bus.sel.eq(0)
284+
yield Delay(1e-6)
285+
self.assertEqual((yield sub_bus.sel), 0b0000)
286+
287+
sim = Simulator(dut)
288+
sim.add_process(sim_test)
289+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
290+
sim.run()
291+
292+
def test_conv_addr_width(self):
293+
intr_bus = Interface(addr_width=12, data_width=8)
294+
sub_bus = Interface(addr_width=10, data_width=32, granularity=8)
295+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
296+
297+
def sim_test():
298+
yield intr_bus.adr.eq(1)
299+
yield intr_bus.sel.eq(1)
300+
yield intr_bus.dat_w.eq(0xA5)
301+
yield sub_bus.dat_r.eq(0x03020100)
302+
yield Delay(1e-6)
303+
self.assertEqual((yield sub_bus.sel), 0b0010)
304+
self.assertEqual((yield sub_bus.dat_w), 0xA5A5A5A5)
305+
self.assertEqual((yield intr_bus.dat_r), 0x01)
306+
307+
sim = Simulator(dut)
308+
sim.add_process(sim_test)
309+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
310+
sim.run()
311+
312+
def test_conv_granularity_addr_width(self):
313+
intr_bus = Interface(addr_width=11, data_width=16)
314+
sub_bus = Interface(addr_width=10, data_width=32, granularity=8)
315+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
316+
317+
def sim_test():
318+
yield intr_bus.adr.eq(3)
319+
yield intr_bus.sel.eq(1)
320+
yield intr_bus.dat_w.eq(0xA55A)
321+
yield sub_bus.dat_r.eq(0x03020100)
322+
yield Delay(1e-6)
323+
self.assertEqual((yield sub_bus.sel), 0b1100)
324+
self.assertEqual((yield sub_bus.dat_w), 0xA55AA55A)
325+
self.assertEqual((yield intr_bus.dat_r), 0x0302)
326+
327+
sim = Simulator(dut)
328+
sim.add_process(sim_test)
329+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
330+
sim.run()
331+
332+
def test_pipelined_initiator(self):
333+
intr_bus = Interface(addr_width=10, data_width=8, features={"stall"})
334+
sub_bus = Interface(addr_width=10, data_width=8)
335+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
336+
337+
def sim_test():
338+
yield intr_bus.adr.eq(1)
339+
yield intr_bus.sel.eq(1)
340+
yield intr_bus.cyc.eq(1)
341+
yield intr_bus.stb.eq(1)
342+
yield Delay(1e-7)
343+
self.assertEqual((yield sub_bus.cyc), 1)
344+
self.assertEqual((yield sub_bus.stb), 1)
345+
self.assertEqual((yield intr_bus.ack), 0)
346+
self.assertEqual((yield intr_bus.stall), 1)
347+
yield Delay(1e-7)
348+
yield sub_bus.ack.eq(1)
349+
yield Delay(1e-7)
350+
self.assertEqual((yield intr_bus.stall), 0)
351+
352+
sim = Simulator(dut)
353+
sim.add_process(sim_test)
354+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
355+
sim.run()
356+
357+
def test_pipelined_subordinate(self):
358+
intr_bus = Interface(addr_width=10, data_width=8)
359+
sub_bus = Interface(addr_width=10, data_width=8, features={"stall"})
360+
dut = Connector(intr_bus=intr_bus, sub_bus=sub_bus)
361+
362+
def sim_test():
363+
yield intr_bus.adr.eq(1)
364+
yield intr_bus.sel.eq(1)
365+
yield intr_bus.cyc.eq(1)
366+
yield intr_bus.stb.eq(1)
367+
yield Delay(1e-8)
368+
self.assertEqual((yield sub_bus.cyc), 1)
369+
self.assertEqual((yield sub_bus.stb), 1)
370+
self.assertEqual((yield intr_bus.ack), 0)
371+
yield
372+
yield sub_bus.ack.eq(1)
373+
yield Delay(1e-8)
374+
self.assertEqual((yield intr_bus.ack), 1)
375+
yield intr_bus.stb.eq(0)
376+
yield
377+
self.assertEqual((yield intr_bus.ack), 1)
378+
yield sub_bus.ack.eq(0)
379+
yield
380+
self.assertEqual((yield intr_bus.ack), 0)
381+
382+
sim = Simulator(dut)
383+
sim.add_clock(1e-6)
384+
sim.add_sync_process(sim_test)
385+
with sim.write_vcd(vcd_file=open("test.vcd", "w")):
386+
sim.run()
387+
388+
126389
class DecoderTestCase(unittest.TestCase):
127390
def setUp(self):
128391
self.dut = Decoder(addr_width=31, data_width=32, granularity=16)

0 commit comments

Comments
 (0)