diff --git a/examples/dataflow_dma.py b/examples/dataflow_dma.py index b5f24a7cf..a6ccd9a34 100644 --- a/examples/dataflow_dma.py +++ b/examples/dataflow_dma.py @@ -9,22 +9,18 @@ from migen.bus import wishbone from migen.sim.generic import Simulator from migen.sim.icarus import Runner -class MyPeripheral: +class MyModel: def __init__(self): - self.bus = wishbone.Interface() - self.ack_en = Signal() self.prng = Random(763627) - - def do_simulation(self, s): - # Only authorize acks on certain cycles to simulate variable latency. - s.wr(self.ack_en, self.prng.randrange(0, 2)) - - def get_fragment(self): - comb = [ - self.bus.ack.eq(self.bus.cyc & self.bus.stb & self.ack_en), - self.bus.dat_r.eq(self.bus.adr + 4) - ] - return Fragment(comb, sim=[self.do_simulation]) + + def read(self, address): + return address + 4 + + def write(self, address, data, sel): + pass + + def can_ack(self, bus): + return self.prng.randrange(0, 2) def adrgen_gen(): for i in range(10): @@ -47,7 +43,7 @@ def test_reader(): g.add_connection(reader, dumper) comp = CompositeActor(g) - peripheral = MyPeripheral() + peripheral = wishbone.Target(MyModel()) interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus) def end_simulation(s): @@ -76,7 +72,7 @@ def test_writer(): g.add_connection(trgen, writer) comp = CompositeActor(g) - peripheral = MyPeripheral() + peripheral = wishbone.Target(MyModel()) tap = wishbone.Tap(peripheral.bus) interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus) diff --git a/examples/wb_initiator.py b/examples/wb_initiator.py index d5e38adcd..607de6963 100644 --- a/examples/wb_initiator.py +++ b/examples/wb_initiator.py @@ -33,31 +33,26 @@ def my_generator(): yield None # Our bus slave. -# All transactions complete with a random delay. -# Reads return address + 4. Writes are simply acknowledged. -class MyPeripheral: +class MyModel: def __init__(self): - self.bus = wishbone.Interface() - self.ack_en = Signal() self.prng = Random(763627) - - def do_simulation(self, s): - # Only authorize acks on certain cycles to simulate variable latency. - s.wr(self.ack_en, self.prng.randrange(0, 2)) - - def get_fragment(self): - comb = [ - self.bus.ack.eq(self.bus.cyc & self.bus.stb & self.ack_en), - self.bus.dat_r.eq(self.bus.adr + 4) - ] - return Fragment(comb, sim=[self.do_simulation]) + + def read(self, address): + return address + 4 + + def write(self, address, data, sel): + pass + + def can_ack(self, bus): + return self.prng.randrange(0, 2) def main(): # The "wishbone.Initiator" library component runs our generator # and manipulates the bus signals accordingly. master = wishbone.Initiator(my_generator()) - # Our slave. - slave = MyPeripheral() + # The "wishbone.Target" library component examines the bus signals + # and calls into our model object. + slave = wishbone.Target(MyModel()) # The "wishbone.Tap" library component examines the bus at the slave port # and displays the transactions on the console (/). tap = wishbone.Tap(slave.bus) diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index 83b27fe32..d7a400ae4 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -3,6 +3,7 @@ from migen.corelogic import roundrobin from migen.corelogic.misc import multimux, optree from migen.bus.simple import * from migen.bus.transactions import * +from migen.sim.generic import Proxy _desc = Description( (M_TO_S, "adr", 30), @@ -186,3 +187,27 @@ class Initiator: def get_fragment(self): return Fragment(sim=[self.do_simulation]) + +class Target: + def __init__(self, model): + self.bus = Interface() + self.model = model + + def do_simulation(self, s): + bus = Proxy(s, self.bus) + if not bus.ack: + if hasattr(self.model, "can_ack"): + can_ack = self.model.can_ack(bus) + else: + can_ack = True + if can_ack and bus.cyc and bus.stb: + if bus.we: + self.model.write(bus.adr, bus.dat_w, bus.sel) + else: + bus.dat_r = self.model.read(bus.adr) + bus.ack = 1 + else: + bus.ack = 0 + + def get_fragment(self): + return Fragment(sim=[self.do_simulation])