actorlib: WB reader simulation OK

This commit is contained in:
Sebastien Bourdeauducq 2012-06-08 21:31:05 +02:00
parent 11674242c4
commit 356051e8a8
2 changed files with 132 additions and 90 deletions

View File

@ -1,27 +1,97 @@
import networkx as nx import networkx as nx
from random import Random
from migen.fhdl import verilog from migen.fhdl import verilog
from migen.flow.ala import * from migen.flow.ala import *
from migen.flow.network import * from migen.flow.network import *
from migen.actorlib import dma_wishbone, control from migen.actorlib import dma_wishbone
from migen.actorlib.sim import *
from migen.bus import wishbone
from migen.sim.generic import Simulator
from migen.sim.icarus import Runner
L = [ class MyPeripheral:
("x", BV(10), 8), def __init__(self):
("y", BV(10), 8), self.bus = wishbone.Interface()
("level2", [ self.ack_en = Signal()
("a", BV(5), 32), self.prng = Random(763627)
("b", BV(5), 16)
])
]
adrgen = control.For(10) def do_simulation(self, s):
reader = dma_wishbone.Reader(L) # Only authorize acks on certain cycles to simulate variable latency.
s.wr(self.ack_en, self.prng.randrange(0, 2))
g = nx.MultiDiGraph() def get_fragment(self):
add_connection(g, adrgen, reader) comb = [
comp = CompositeActor(g) 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])
frag = comp.get_fragment() def adrgen_gen():
ios = set(reader.bus.signals()) for i in range(10):
ios.add(comp.busy) print("Address: " + str(i))
print(verilog.convert(frag, ios=ios)) yield Token("address", {"a": i})
def dumper_gen():
while True:
t = Token("data")
yield t
print("Received: " + str(t.value["d"]))
def test_reader():
print("*** Testing reader")
adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))]))
reader = dma_wishbone.Reader()
dumper = SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))]))
g = nx.MultiDiGraph()
add_connection(g, adrgen, reader)
add_connection(g, reader, dumper)
comp = CompositeActor(g)
peripheral = MyPeripheral()
interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus)
def end_simulation(s):
s.interrupt = adrgen.done and not s.rd(comp.busy)
fragment = comp.get_fragment() \
+ peripheral.get_fragment() \
+ interconnect.get_fragment() \
+ Fragment(sim=[end_simulation])
sim = Simulator(fragment, Runner())
sim.run()
def trgen_gen():
for i in range(10):
a = i
d = i+10
print("Address: " + str(a) + " Data: " + str(d))
yield Token("address_data", {"a": a, "d": d})
def test_writer():
print("*** Testing writer")
trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))]))
writer = dma_wishbone.Reader()
g = nx.MultiDiGraph()
add_connection(g, trgen, writer)
comp = CompositeActor(g)
peripheral = MyPeripheral()
tap = wishbone.Tap(peripheral.bus)
interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus)
def end_simulation(s):
s.interrupt = trgen.done and not s.rd(comp.busy)
fragment = comp.get_fragment() \
+ peripheral.get_fragment() \
+ tap.get_fragment() \
+ interconnect.get_fragment() \
+ Fragment(sim=[end_simulation])
sim = Simulator(fragment, Runner())
sim.run()
test_reader()
test_writer()

View File

@ -1,86 +1,58 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.corelogic.record import *
from migen.corelogic.fsm import *
from migen.bus import wishbone from migen.bus import wishbone
from migen.flow.actor import * from migen.flow.actor import *
class Reader(Actor): class Reader(Actor):
def __init__(self, layout): def __init__(self):
self.bus = wishbone.Master() self.bus = wishbone.Interface()
Actor.__init__(self, super().__init__(
SchedulingModel(SchedulingModel.DYNAMIC),
("address", Sink, [("a", BV(30))]), ("address", Sink, [("a", BV(30))]),
("data", Source, layout)) ("data", Source, [("d", BV(32))]))
def get_fragment(self): def get_fragment(self):
components, length = self.token("data").flatten(align=True, return_offset=True) bus_stb = Signal()
nwords = (length + 31)//32
# Address generator data_reg_loaded = Signal()
ag_stb = Signal() data_reg = Signal(BV(32))
ag_sync = [If(ag_stb, self.bus.adr_o.eq(self.token("address").a))]
if nwords > 1:
ag_inc = Signal()
ag_sync.append(If(ag_inc, self.bus.adr_o.eq(self.bus.adr_o + 1)))
address_generator = Fragment(sync=ag_sync)
# Output buffer comb = [
ob_reg = Signal(BV(length)) self.busy.eq(data_reg_loaded),
ob_stbs = Signal(BV(nwords)) self.bus.we.eq(0),
ob_sync = [] bus_stb.eq(self.endpoints["address"].stb & (~data_reg_loaded | self.endpoints["data"].ack)),
top = length self.bus.cyc.eq(bus_stb),
for w in range(nwords): self.bus.stb.eq(bus_stb),
if top >= 32: self.bus.adr.eq(self.token("address").a),
width = 32 self.endpoints["address"].ack.eq(self.bus.ack),
sl = self.bus.dat_i self.endpoints["data"].stb.eq(data_reg_loaded),
else: self.token("data").d.eq(data_reg)
width = top ]
sl = self.bus.dat_i[32-top:] sync = [
ob_sync.append(If(ob_stbs[w], If(self.endpoints["data"].ack,
ob_reg[top-width:top].eq(sl))) data_reg_loaded.eq(0)
top -= width ),
ob_comb = [] If(self.bus.ack,
offset = 0 data_reg_loaded.eq(1),
for s in components: data_reg.eq(self.bus.dat_r)
w = s.bv.width
if isinstance(s, Signal):
ob_comb.append(s.eq(ob_reg[length-offset-w:length-offset]))
offset += w
output_buffer = Fragment(ob_comb, ob_sync)
# Controller
fetch_states = ["FETCH{0}".format(w) for w in range(nwords)]
states = ["IDLE"] + fetch_states + ["STROBE"]
fsm = FSM(*states)
self.busy.reset = Constant(1)
fsm.act(fsm.IDLE,
self.busy.eq(0),
ag_stb.eq(1),
self.endpoints["address"].ack.eq(1),
If(self.endpoints["address"].stb, fsm.next_state(fsm.FETCH0))
)
for w in range(nwords):
state = getattr(fsm, fetch_states[w])
if w == nwords - 1:
next_state = fsm.STROBE
else:
next_state = getattr(fsm, fetch_states[w+1])
fsm.act(state,
self.bus.cyc_o.eq(1),
self.bus.stb_o.eq(1),
ob_stbs[w].eq(1),
If(self.bus.ack_i,
fsm.next_state(next_state),
ag_inc.eq(1) if nwords > 1 else None
)
) )
fsm.act(fsm.STROBE, ]
self.endpoints["data"].stb.eq(1),
If(self.endpoints["data"].ack, fsm.next_state(fsm.IDLE))
)
controller = fsm.get_fragment()
return address_generator + output_buffer + controller return Fragment(comb, sync)
class Writer(Actor): class Writer(Actor):
pass # TODO def __init__(self):
self.bus = wishbone.Interface()
super().__init__(
("address_data", Sink, [("a", BV(30)), ("d", BV(32))]))
def get_fragment(self):
comb = [
self.busy.eq(0),
self.bus.we.eq(1),
self.bus.cyc.eq(self.endpoints["address_data"].stb),
self.bus.stb.eq(self.endpoints["address_data"].stb),
self.bus.adr.eq(self.token("address_data").a),
self.bus.sel.eq(0xf),
self.bus.dat_w.eq(self.token("address_data").d),
self.endpoints["address_data"].ack.eq(self.bus.ack)
]
return Fragment(comb)