flow: use Module and new Record APIs

This commit is contained in:
Sebastien Bourdeauducq 2013-04-10 19:12:42 +02:00
parent 20bdd424c8
commit 692794a21f
20 changed files with 481 additions and 551 deletions

View File

@ -1,5 +1,6 @@
from random import Random
from migen.fhdl.module import Module
from migen.flow.network import *
from migen.flow.transactions import *
from migen.actorlib import dma_wishbone, dma_asmi
@ -26,12 +27,22 @@ def adrgen_gen():
print("Address: " + str(i))
yield Token("address", {"a": i})
class SimAdrGen(SimActor):
def __init__(self, nbits):
self.address = Source([("a", nbits)])
SimActor.__init__(self, adrgen_gen())
def dumper_gen():
while True:
t = Token("data", idle_wait=True)
yield t
print("Received: " + str(t.value["d"]))
class SimDumper(SimActor):
def __init__(self):
self.data = Sink([("d", 32)])
SimActor.__init__(self, dumper_gen())
def trgen_gen():
for i in range(10):
a = i
@ -39,75 +50,78 @@ def trgen_gen():
print("Address: " + str(a) + " Data: " + str(d))
yield Token("address_data", {"a": a, "d": d})
def wishbone_sim(efragment, master, end_simulation):
peripheral = wishbone.Target(MyModelWB())
tap = wishbone.Tap(peripheral.bus)
interconnect = wishbone.InterconnectPointToPoint(master.bus, peripheral.bus)
def _end_simulation(s):
s.interrupt = end_simulation(s)
fragment = efragment \
+ peripheral.get_fragment() \
+ tap.get_fragment() \
+ interconnect.get_fragment() \
+ Fragment(sim=[_end_simulation])
sim = Simulator(fragment)
sim.run()
class SimTrGen(SimActor):
def __init__(self):
self.address_data = Source([("a", 30), ("d", 32)])
SimActor.__init__(self, trgen_gen())
def asmi_sim(efragment, hub, end_simulation):
def _end_simulation(s):
s.interrupt = end_simulation(s)
peripheral = asmibus.Target(MyModelASMI(), hub)
tap = asmibus.Tap(hub)
def _end_simulation(s):
s.interrupt = end_simulation(s)
fragment = efragment \
+ peripheral.get_fragment() \
+ tap.get_fragment() \
+ Fragment(sim=[_end_simulation])
sim = Simulator(fragment)
sim.run()
class TBWishbone(Module):
def __init__(self, master):
self.submodules.peripheral = wishbone.Target(MyModelWB())
self.submodules.tap = wishbone.Tap(self.peripheral.bus)
self.submodules.interconnect = wishbone.InterconnectPointToPoint(master.bus,
self.peripheral.bus)
class TBWishboneReader(TBWishbone):
def __init__(self):
self.adrgen = SimAdrGen(30)
self.reader = dma_wishbone.Reader()
self.dumper = SimDumper()
g = DataFlowGraph()
g.add_connection(self.adrgen, self.reader)
g.add_connection(self.reader, self.dumper)
self.submodules.comp = CompositeActor(g)
TBWishbone.__init__(self, self.reader)
def do_simulation(self, s):
s.interrupt = self.adrgen.token_exchanger.done and not s.rd(self.comp.busy)
class TBWishboneWriter(TBWishbone):
def __init__(self):
self.trgen = SimTrGen()
self.writer = dma_wishbone.Writer()
g = DataFlowGraph()
g.add_connection(self.trgen, self.writer)
self.submodules.comp = CompositeActor(g)
TBWishbone.__init__(self, self.writer)
def do_simulation(self, s):
s.interrupt = self.trgen.token_exchanger.done and not s.rd(self.comp.busy)
class TBAsmi(Module):
def __init__(self, hub):
self.submodules.peripheral = asmibus.Target(MyModelASMI(), hub)
self.submodules.tap = asmibus.Tap(hub)
class TBAsmiReader(TBAsmi):
def __init__(self, nslots):
self.submodules.hub = asmibus.Hub(32, 32)
port = self.hub.get_port(nslots)
self.hub.finalize()
self.adrgen = SimAdrGen(32)
self.reader = dma_asmi.Reader(port)
self.dumper = SimDumper()
g = DataFlowGraph()
g.add_connection(self.adrgen, self.reader)
g.add_connection(self.reader, self.dumper)
self.submodules.comp = CompositeActor(g)
TBAsmi.__init__(self, self.hub)
def do_simulation(self, s):
s.interrupt = self.adrgen.token_exchanger.done and not s.rd(self.comp.busy)
def test_wb_reader():
print("*** Testing Wishbone reader")
adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", 30)]))
reader = dma_wishbone.Reader()
dumper = SimActor(dumper_gen(), ("data", Sink, [("d", 32)]))
g = DataFlowGraph()
g.add_connection(adrgen, reader)
g.add_connection(reader, dumper)
comp = CompositeActor(g)
wishbone_sim(comp.get_fragment(), reader,
lambda s: adrgen.token_exchanger.done and not s.rd(comp.busy))
Simulator(TBWishboneReader()).run()
def test_wb_writer():
print("*** Testing Wishbone writer")
trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", 30), ("d", 32)]))
writer = dma_wishbone.Writer()
g = DataFlowGraph()
g.add_connection(trgen, writer)
comp = CompositeActor(g)
wishbone_sim(comp.get_fragment(), writer,
lambda s: trgen.token_exchanger.done and not s.rd(comp.busy))
Simulator(TBWishboneWriter()).run()
def test_asmi_reader(nslots):
print("*** Testing ASMI reader (nslots={})".format(nslots))
hub = asmibus.Hub(32, 32)
port = hub.get_port(nslots)
hub.finalize()
adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", 32)]))
reader = dma_asmi.Reader(port)
dumper = SimActor(dumper_gen(), ("data", Sink, [("d", 32)]))
g = DataFlowGraph()
g.add_connection(adrgen, reader)
g.add_connection(reader, dumper)
comp = CompositeActor(g)
asmi_sim(hub.get_fragment() + comp.get_fragment(), hub,
lambda s: adrgen.token_exchanger.done and not s.rd(comp.busy))
Simulator(TBAsmiReader(nslots)).run()
test_wb_reader()
test_wb_writer()

View File

@ -8,7 +8,12 @@ def source_gen():
for i in range(10):
v = i + 5
print("==> " + str(v))
yield Token("source", {"value": v})
yield Token("source", {"maximum": v})
class SimSource(SimActor):
def __init__(self):
self.source = Source([("maximum", 32)])
SimActor.__init__(self, source_gen())
def sink_gen():
while True:
@ -16,16 +21,20 @@ def sink_gen():
yield t
print(t.value["value"])
class SimSink(SimActor):
def __init__(self):
self.sink = Sink([("value", 32)])
SimActor.__init__(self, sink_gen())
def main():
source = SimActor(source_gen(), ("source", Source, [("value", 32)]))
source = SimSource()
loop = misc.IntSequence(32)
sink = SimActor(sink_gen(), ("sink", Sink, [("value", 32)]))
sink = SimSink()
g = DataFlowGraph()
g.add_connection(source, loop)
g.add_connection(loop, sink)
comp = CompositeActor(g)
fragment = comp.get_fragment()
sim = Simulator(fragment)
sim = Simulator(comp)
sim.run(500)
main()

View File

@ -11,48 +11,57 @@ from migen.sim.generic import Simulator
from migen.flow import perftools
pack_factor = 5
base_layout = [("value", 32)]
packed_layout = structuring.pack_layout(base_layout, pack_factor)
rawbits_layout = [("value", 32*pack_factor)]
def source_gen():
for i in count(0):
yield Token("source", {"value": i})
class SimSource(SimActor):
def __init__(self):
self.source = Source(base_layout)
SimActor.__init__(self, source_gen())
def sink_gen():
while True:
t = Token("sink")
yield t
print(t.value["value"])
class SimSink(SimActor):
def __init__(self):
self.sink = Sink(base_layout)
SimActor.__init__(self, sink_gen())
class TB(Module):
def __init__(self):
source = SimSource()
sink = SimSink()
# A tortuous way of passing integer tokens.
packer = structuring.Pack(base_layout, pack_factor)
to_raw = structuring.Cast(packed_layout, rawbits_layout)
from_raw = structuring.Cast(rawbits_layout, packed_layout)
unpacker = structuring.Unpack(pack_factor, base_layout)
self.g = DataFlowGraph()
self.g.add_connection(source, packer)
self.g.add_connection(packer, to_raw)
self.g.add_connection(to_raw, from_raw)
self.g.add_connection(from_raw, unpacker)
self.g.add_connection(unpacker, sink)
self.submodules.comp = CompositeActor(self.g)
self.submodules.reporter = perftools.DFGReporter(self.g)
def main():
base_layout = [("value", 32)]
packed_layout = structuring.pack_layout(base_layout, pack_factor)
rawbits_layout = [("value", 32*pack_factor)]
tb = TB()
sim = Simulator(tb).run(1000)
source = SimActor(source_gen(), ("source", Source, base_layout))
sink = SimActor(sink_gen(), ("sink", Sink, base_layout))
# A tortuous way of passing integer tokens.
packer = structuring.Pack(base_layout, pack_factor)
to_raw = structuring.Cast(packed_layout, rawbits_layout)
from_raw = structuring.Cast(rawbits_layout, packed_layout)
unpacker = structuring.Unpack(pack_factor, base_layout)
g = DataFlowGraph()
g.add_connection(source, packer)
g.add_connection(packer, to_raw)
g.add_connection(to_raw, from_raw)
g.add_connection(from_raw, unpacker)
g.add_connection(unpacker, sink)
comp = CompositeActor(g)
reporter = perftools.DFGReporter(g)
fragment = comp.get_fragment() + reporter.get_fragment()
sim = Simulator(fragment)
sim.run(1000)
g_layout = nx.spectral_layout(g)
nx.draw(g, g_layout)
nx.draw_networkx_edge_labels(g, g_layout, reporter.get_edge_labels())
g_layout = nx.spectral_layout(tb.g)
nx.draw(tb.g, g_layout)
nx.draw_networkx_edge_labels(tb.g, g_layout, tb.reporter.get_edge_labels())
plt.show()
main()

View File

@ -11,6 +11,11 @@ def number_gen():
for i in range(10):
yield Token("result", {"r": i})
class SimNumberGen(SimActor):
def __init__(self):
self.result = Source(layout)
SimActor.__init__(self, number_gen())
def run_sim(ng):
g = DataFlowGraph()
d = Dumper(layout)
@ -23,7 +28,7 @@ def run_sim(ng):
def main():
print("Simulating native Python:")
ng_native = SimActor(number_gen(), ("result", Source, layout))
ng_native = SimNumberGen()
run_sim(ng_native)
print("Simulating Pytholite:")
@ -31,6 +36,7 @@ def main():
run_sim(ng_pytholite)
print("Converting Pytholite to Verilog:")
ng_pytholite = make_pytholite(number_gen, dataflow=[("result", Source, layout)])
print(verilog.convert(ng_pytholite))
main()

View File

@ -66,6 +66,9 @@ def main():
run_sim(ng_pytholite)
print("Converting Pytholite to Verilog:")
ng_pytholite = make_pytholite(gen,
dataflow=dataflow,
buses=buses)
print(verilog.convert(ng_pytholite.get_fragment()))
main()

View File

@ -10,22 +10,31 @@ def source_gen():
print("Sending: " + str(i))
yield Token("source", {"value": i})
class SimSource(SimActor):
def __init__(self):
self.source = Source([("value", 32)])
SimActor.__init__(self, source_gen())
def sink_gen():
while True:
t = Token("sink")
yield t
print("Received: " + str(t.value["value"]))
def main():
source = SimActor(source_gen(), ("source", Source, [("value", 32)]))
sink = SimActor(sink_gen(), ("sink", Sink, [("value", 32)]))
g = DataFlowGraph()
g.add_connection(source, sink)
comp = CompositeActor(g)
def end_simulation(s):
s.interrupt = source.token_exchanger.done
fragment = comp.get_fragment() + Fragment(sim=[end_simulation])
sim = Simulator(fragment)
sim.run()
class SimSink(SimActor):
def __init__(self):
self.sink = Sink([("value", 32)])
SimActor.__init__(self, sink_gen())
main()
class TB(Module):
def __init__(self):
self.source = SimSource()
self.sink = SimSink()
g = DataFlowGraph()
g.add_connection(self.source, self.sink)
self.submodules.comp = CompositeActor(g)
def do_simulation(self, s):
s.interrupt = self.source.token_exchanger.done
Simulator(TB()).run()

View File

@ -1,91 +1,83 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.flow.actor import *
from migen.genlib.buffers import ReorderBuffer
class SequentialReader(Actor):
class SequentialReader(Module):
def __init__(self, port):
self.port = port
assert(len(self.port.slots) == 1)
Actor.__init__(self,
("address", Sink, [("a", self.port.hub.aw)]),
("data", Source, [("d", self.port.hub.dw)]))
assert(len(port.slots) == 1)
self.address = Sink([("a", port.hub.aw)])
self.data = Source([("d", port.hub.dw)])
self.busy = Signal()
def get_fragment(self):
###
sample = Signal()
data_reg_loaded = Signal()
data_reg = Signal(self.port.hub.dw)
data_reg = Signal(port.hub.dw)
accept_new = Signal()
# We check that len(self.port.slots) == 1
# and therefore we can assume that self.port.ack
# We check that len(port.slots) == 1
# and therefore we can assume that port.ack
# goes low until the data phase.
comb = [
self.busy.eq(~data_reg_loaded | ~self.port.ack),
self.port.adr.eq(self.token("address").a),
self.port.we.eq(0),
accept_new.eq(~data_reg_loaded | self.endpoints["data"].ack),
self.port.stb.eq(self.endpoints["address"].stb & accept_new),
self.endpoints["address"].ack.eq(self.port.ack & accept_new),
self.endpoints["data"].stb.eq(data_reg_loaded),
self.token("data").d.eq(data_reg)
self.comb += [
self.busy.eq(~data_reg_loaded | ~port.ack),
port.adr.eq(self.address.payload.a),
port.we.eq(0),
accept_new.eq(~data_reg_loaded | self.data.ack),
port.stb.eq(self.address.stb & accept_new),
self.address.ack.eq(port.ack & accept_new),
self.data.stb.eq(data_reg_loaded),
self.data.payload.d.eq(data_reg)
]
sync = [
If(self.endpoints["data"].ack,
data_reg_loaded.eq(0)
),
self.sync += [
If(self.data.ack, data_reg_loaded.eq(0)),
If(sample,
data_reg_loaded.eq(1),
data_reg.eq(self.port.dat_r)
data_reg.eq(port.dat_r)
),
sample.eq(self.port.get_call_expression())
sample.eq(port.get_call_expression())
]
return Fragment(comb, sync)
class OOOReader(Actor):
class OOOReader(Module):
def __init__(self, port):
self.port = port
assert(len(self.port.slots) > 1)
Actor.__init__(self,
("address", Sink, [("a", self.port.hub.aw)]),
("data", Source, [("d", self.port.hub.dw)]))
assert(len(port.slots) > 1)
self.address = Sink([("a", port.hub.aw)])
self.data = Source([("d", port.hub.dw)])
self.busy = Signal() # TODO: drive busy
def get_fragment(self):
tag_width = len(self.port.tag_call)
data_width = self.port.hub.dw
depth = len(self.port.slots)
###
tag_width = len(port.tag_call)
data_width = port.hub.dw
depth = len(port.slots)
rob = ReorderBuffer(tag_width, data_width, depth)
self.submodules += rob
comb = [
self.port.adr.eq(self.token("address").a),
self.port.we.eq(0),
self.port.stb.eq(self.endpoints["address"].stb & rob.can_issue),
self.endpoints["address"].ack.eq(self.port.ack & rob.can_issue),
rob.issue.eq(self.endpoints["address"].stb & self.port.ack),
rob.tag_issue.eq(self.port.base + self.port.tag_issue),
self.comb += [
port.adr.eq(self.address.payload.a),
port.we.eq(0),
port.stb.eq(self.address.stb & rob.can_issue),
self.address.ack.eq(port.ack & rob.can_issue),
rob.issue.eq(self.address.stb & port.ack),
rob.tag_issue.eq(port.base + port.tag_issue),
rob.data_call.eq(self.port.dat_r),
rob.data_call.eq(port.dat_r),
self.endpoints["data"].stb.eq(rob.can_read),
rob.read.eq(self.endpoints["data"].ack),
self.token("data").d.eq(rob.data_read)
self.data.stb.eq(rob.can_read),
rob.read.eq(self.data.ack),
self.data.payload.d.eq(rob.data_read)
]
sync = [
self.sync += [
# Data is announced one cycle in advance.
# Register the call to synchronize it with the data signal.
rob.call.eq(self.port.call),
rob.tag_call.eq(self.port.tag_call)
rob.call.eq(port.call),
rob.tag_call.eq(port.tag_call)
]
return Fragment(comb, sync) + rob.get_fragment()
class Reader:
def __init__(self, port):
if len(port.slots) == 1:
self.__class__ = SequentialReader
SequentialReader.__init__(self, port)
else:
self.__class__ = OOOReader
OOOReader.__init__(self, port)
def Reader(port):
if len(port.slots) == 1:
return SequentialReader(port)
else:
return OOOReader(port)

View File

@ -1,58 +1,55 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.bus import wishbone
from migen.flow.actor import *
class Reader(Actor):
class Reader(Module):
def __init__(self):
self.bus = wishbone.Interface()
Actor.__init__(self,
("address", Sink, [("a", 30)]),
("data", Source, [("d", 32)]))
self.address = Sink([("a", 30)])
self.data = Source([("d", 32)])
self.busy = Signal()
###
def get_fragment(self):
bus_stb = Signal()
data_reg_loaded = Signal()
data_reg = Signal(32)
comb = [
self.comb += [
self.busy.eq(data_reg_loaded),
self.bus.we.eq(0),
bus_stb.eq(self.endpoints["address"].stb & (~data_reg_loaded | self.endpoints["data"].ack)),
bus_stb.eq(self.address.stb & (~data_reg_loaded | self.data.ack)),
self.bus.cyc.eq(bus_stb),
self.bus.stb.eq(bus_stb),
self.bus.adr.eq(self.token("address").a),
self.endpoints["address"].ack.eq(self.bus.ack),
self.endpoints["data"].stb.eq(data_reg_loaded),
self.token("data").d.eq(data_reg)
self.bus.adr.eq(self.address.payload.a),
self.address.ack.eq(self.bus.ack),
self.data.stb.eq(data_reg_loaded),
self.data.payload.d.eq(data_reg)
]
sync = [
If(self.endpoints["data"].ack,
data_reg_loaded.eq(0)
),
self.sync += [
If(self.data.ack, data_reg_loaded.eq(0)),
If(self.bus.ack,
data_reg_loaded.eq(1),
data_reg.eq(self.bus.dat_r)
)
]
return Fragment(comb, sync)
class Writer(Actor):
class Writer(Module):
def __init__(self):
self.bus = wishbone.Interface()
Actor.__init__(self,
("address_data", Sink, [("a", 30), ("d", 32)]))
self.address_data = Sink([("a", 30), ("d", 32)])
self.busy = Signal()
def get_fragment(self):
comb = [
###
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.cyc.eq(self.address_data.stb),
self.bus.stb.eq(self.address_data.stb),
self.bus.adr.eq(self.address_data.payload.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)
self.bus.dat_w.eq(self.address_data.payload.d),
self.address_data.ack.eq(self.bus.ack)
]
return Fragment(comb)

View File

@ -1,68 +1,65 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.genlib.record import *
from migen.genlib.fsm import *
from migen.flow.actor import *
# Generates integers from start to maximum-1
class IntSequence(Actor):
class IntSequence(Module):
def __init__(self, nbits, offsetbits=0, step=1):
self.nbits = nbits
self.offsetbits = offsetbits
self.step = step
parameters_layout = [("maximum", nbits)]
if offsetbits:
parameters_layout.append(("offset", offsetbits))
parameters_layout = [("maximum", self.nbits)]
if self.offsetbits:
parameters_layout.append(("offset", self.offsetbits))
Actor.__init__(self,
("parameters", Sink, parameters_layout),
("source", Source, [("value", max(self.nbits, self.offsetbits))]))
self.parameters = Sink(parameters_layout)
self.source = Source([("value", max(nbits, offsetbits))])
self.busy = Signal()
###
def get_fragment(self):
load = Signal()
ce = Signal()
last = Signal()
maximum = Signal(self.nbits)
if self.offsetbits:
offset = Signal(self.offsetbits)
counter = Signal(self.nbits)
maximum = Signal(nbits)
if offsetbits:
offset = Signal(offsetbits)
counter = Signal(nbits)
if self.step > 1:
comb = [last.eq(counter + self.step >= maximum)]
if step > 1:
self.comb += last.eq(counter + step >= maximum)
else:
comb = [last.eq(counter + 1 == maximum)]
sync = [
self.comb += last.eq(counter + 1 == maximum)
self.sync += [
If(load,
counter.eq(0),
maximum.eq(self.token("parameters").maximum),
offset.eq(self.token("parameters").offset) if self.offsetbits else None
maximum.eq(self.parameters.payload.maximum),
offset.eq(self.parameters.payload.offset) if offsetbits else None
).Elif(ce,
If(last,
counter.eq(0)
).Else(
counter.eq(counter + self.step)
counter.eq(counter + step)
)
)
]
if self.offsetbits:
comb.append(self.token("source").value.eq(counter + offset))
if offsetbits:
self.comb += self.source.payload.value.eq(counter + offset)
else:
comb.append(self.token("source").value.eq(counter))
counter_fragment = Fragment(comb, sync)
self.comb += self.source.payload.value.eq(counter)
fsm = FSM("IDLE", "ACTIVE")
self.submodules += fsm
fsm.act(fsm.IDLE,
load.eq(1),
self.endpoints["parameters"].ack.eq(1),
If(self.endpoints["parameters"].stb, fsm.next_state(fsm.ACTIVE))
self.parameters.ack.eq(1),
If(self.parameters.stb, fsm.next_state(fsm.ACTIVE))
)
fsm.act(fsm.ACTIVE,
self.busy.eq(1),
self.endpoints["source"].stb.eq(1),
If(self.endpoints["source"].ack,
self.source.stb.eq(1),
If(self.source.ack,
ce.eq(1),
If(last, fsm.next_state(fsm.IDLE))
)
)
return counter_fragment + fsm.get_fragment()

View File

@ -20,10 +20,10 @@ class TokenExchanger(Module):
def _process_transactions(self, s):
completed = set()
for token in self.active:
ep = self.actor.endpoints[token.endpoint]
ep = getattr(self.actor, token.endpoint)
if isinstance(ep, Sink):
if s.rd(ep.ack) and s.rd(ep.stb):
token.value = s.multiread(ep.token)
token.value = s.multiread(ep.payload)
completed.add(token)
s.wr(ep.ack, 0)
elif isinstance(ep, Source):
@ -38,11 +38,11 @@ class TokenExchanger(Module):
def _update_control_signals(self, s):
for token in self.active:
ep = self.actor.endpoints[token.endpoint]
ep = getattr(self.actor, token.endpoint)
if isinstance(ep, Sink):
s.wr(ep.ack, 1)
elif isinstance(ep, Source):
s.multiwrite(ep.token, token.value)
s.multiwrite(ep.payload, token.value)
s.wr(ep.stb, 1)
else:
raise TypeError
@ -56,9 +56,7 @@ class TokenExchanger(Module):
transactions = None
if isinstance(transactions, Token):
self.active = {transactions}
elif isinstance(transactions, tuple) \
or isinstance(transactions, list) \
or isinstance(transactions, set):
elif isinstance(transactions, (tuple, list, set)):
self.active = set(transactions)
elif transactions is None:
self.active = set()
@ -77,27 +75,25 @@ class TokenExchanger(Module):
do_simulation.initialize = True
class SimActor(Actor):
def __init__(self, generator, *endpoint_descriptions, **misc):
Actor.__init__(self, *endpoint_descriptions, **misc)
self.token_exchanger = TokenExchanger(generator, self)
class SimActor(Module):
def __init__(self, generator):
self.busy = Signal()
self.submodules.token_exchanger = TokenExchanger(generator, self)
def update_busy(self, s):
def do_simulation(self, s):
s.wr(self.busy, self.token_exchanger.busy)
def get_fragment(self):
return self.token_exchanger.get_fragment() + Fragment(sim=[self.update_busy])
def _dumper_gen(prefix):
while True:
t = Token("result")
yield t
if len(t.value) > 1:
s = str(t.value)
else:
s = str(list(t.value.values())[0])
print(prefix + s)
class Dumper(SimActor):
def __init__(self, layout, prefix=""):
def dumper_gen():
while True:
t = Token("result")
yield t
if len(t.value) > 1:
s = str(t.value)
else:
s = str(list(t.value.values())[0])
print(prefix + s)
SimActor.__init__(self, dumper_gen(),
("result", Sink, layout))
self.result = Sink(layout)
SimActor.__init__(self, _dumper_gen(prefix))

View File

@ -47,41 +47,35 @@ def _create_csrs_assign(layout, target, atomic, prefix=""):
(MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3)
class SingleGenerator(Actor):
class SingleGenerator(Module):
def __init__(self, layout, mode):
self._mode = mode
Actor.__init__(self, ("source", Source, _convert_layout(layout)))
self._csrs, self._assigns = _create_csrs_assign(layout,
self.token("source"), self._mode != MODE_SINGLE_SHOT)
self.source = Source(_convert_layout(layout))
self.busy = Signal()
self._csrs, assigns = _create_csrs_assign(layout, self.source.payload,
mode != MODE_SINGLE_SHOT)
if mode == MODE_EXTERNAL:
self.trigger = Signal()
trigger = self.trigger = Signal()
elif mode == MODE_SINGLE_SHOT:
shoot = CSR()
self._csrs.insert(0, shoot)
self.trigger = shoot.re
trigger = shoot.re
elif mode == MODE_CONTINUOUS:
enable = CSRStorage()
self._csrs.insert(0, enable)
self.trigger = enable.storage
trigger = enable.storage
else:
raise ValueError
self.comb += self.busy.eq(self.source.stb)
stmts = [self.source.stb.eq(trigger)] + assigns
self.sync += [If(self.source.ack | ~self.source.stb, *stmts)]
def get_csrs(self):
return self._csrs
def get_fragment(self):
stb = self.endpoints["source"].stb
ack = self.endpoints["source"].ack
comb = [
self.busy.eq(stb)
]
stmts = [stb.eq(self.trigger)] + self._assigns
sync = [If(ack | ~stb, *stmts)]
return Fragment(comb, sync)
class Collector(Actor, AutoCSR):
class Collector(Module, AutoCSR):
def __init__(self, layout, depth=1024):
Actor.__init__(self, ("sink", Sink, layout))
self.sink = Sink(layout)
self.busy = Signal()
self._depth = depth
self._dw = sum(len(s) for s in self.token("sink").flatten())
@ -89,13 +83,17 @@ class Collector(Actor, AutoCSR):
self._r_wc = CSRStorage(bits_for(self._depth), write_from_dev=True, atomic_write=True)
self._r_ra = CSRStorage(bits_for(self._depth-1))
self._r_rd = CSRStatus(self._dw)
###
def get_fragment(self):
mem = Memory(self._dw, self._depth)
self.specials += mem
wp = mem.get_port(write_capable=True)
rp = mem.get_port()
comb = [
self.comb += [
self.busy.eq(0),
If(self._r_wc.r != 0,
self.endpoints["sink"].ack.eq(1),
If(self.endpoints["sink"].stb,
@ -113,5 +111,3 @@ class Collector(Actor, AutoCSR):
rp.adr.eq(self._r_ra.storage),
self._r_rd.status.eq(rp.dat_r)
]
return Fragment(comb, specials={mem})

View File

@ -1,4 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.flow.actor import *
def _rawbits_layout(l):
@ -9,45 +10,42 @@ def _rawbits_layout(l):
class Cast(CombinatorialActor):
def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False):
self.reverse_from = reverse_from
self.reverse_to = reverse_to
CombinatorialActor.__init__(self,
("sink", Sink, _rawbits_layout(layout_from)),
("source", Source, _rawbits_layout(layout_to)))
self.sink = Sink(_rawbits_layout(layout_from))
self.source = Source(_rawbits_layout(layout_to))
CombinatorialActor.__init__(self)
def get_process_fragment(self):
sigs_from = self.token("sink").flatten()
if self.reverse_from:
###
sigs_from = self.sink.payload.flatten()
if reverse_from:
sigs_from = list(reversed(sigs_from))
sigs_to = self.token("source").flatten()
if self.reverse_to:
sigs_to = self.source.payload.flatten()
if reverse_to:
sigs_to = list(reversed(sigs_to))
if sum(len(s) for s in sigs_from) != sum(len(s) for s in sigs_to):
raise TypeError
return Fragment([
Cat(*sigs_to).eq(Cat(*sigs_from))
])
self.comb += Cat(*sigs_to).eq(Cat(*sigs_from))
def pack_layout(l, n):
return [("chunk"+str(i), l) for i in range(n)]
class Unpack(Actor):
class Unpack(Module):
def __init__(self, n, layout_to):
self.n = n
Actor.__init__(self,
("sink", Sink, pack_layout(layout_to, n)),
("source", Source, layout_to))
self.sink = Sink(pack_layout(layout_to, n))
self.source = Source(layout_to)
self.busy = Signal()
def get_fragment(self):
mux = Signal(max=self.n)
###
mux = Signal(max=n)
last = Signal()
comb = [
last.eq(mux == (self.n-1)),
self.endpoints["source"].stb.eq(self.endpoints["sink"].stb),
self.endpoints["sink"].ack.eq(last & self.endpoints["source"].ack)
self.comb += [
last.eq(mux == (n-1)),
self.source.stb.eq(self.sink.stb),
self.sink.ack.eq(last & self.source.ack)
]
sync = [
If(self.endpoints["source"].stb & self.endpoints["source"].ack,
self.sync += [
If(self.source.stb & self.source.ack,
If(last,
mux.eq(0)
).Else(
@ -56,39 +54,36 @@ class Unpack(Actor):
)
]
cases = {}
for i in range(self.n):
cases[i] = [self.token("source").raw_bits().eq(getattr(self.token("sink"), "chunk"+str(i)).raw_bits())]
comb.append(Case(mux, cases).makedefault())
return Fragment(comb, sync)
for i in range(n):
cases[i] = [self.source.payload.raw_bits().eq(getattr(self.sink.payload, "chunk"+str(i)).raw_bits())]
self.comb += Case(mux, cases).makedefault()
class Pack(Actor):
class Pack(Module):
def __init__(self, layout_from, n):
self.n = n
Actor.__init__(self,
("sink", Sink, layout_from),
("source", Source, pack_layout(layout_from, n)))
self.sink = Sink(layout_from)
self.source = Source(pack_layout(layout_from, n))
self.busy = Signal()
def get_fragment(self):
demux = Signal(max=self.n)
###
demux = Signal(max=n)
load_part = Signal()
strobe_all = Signal()
cases = {}
for i in range(self.n):
cases[i] = [getattr(self.token("source"), "chunk"+str(i)).raw_bits().eq(self.token("sink").raw_bits())]
comb = [
for i in range(n):
cases[i] = [getattr(self.source.payload, "chunk"+str(i)).raw_bits().eq(self.sink.payload.raw_bits())]
self.comb += [
self.busy.eq(strobe_all),
self.endpoints["sink"].ack.eq(~strobe_all | self.endpoints["source"].ack),
self.endpoints["source"].stb.eq(strobe_all),
load_part.eq(self.endpoints["sink"].stb & self.endpoints["sink"].ack)
self.sink.ack.eq(~strobe_all | self.source.ack),
self.source.stb.eq(strobe_all),
load_part.eq(self.sink.stb & self.sink.ack)
]
sync = [
If(self.endpoints["source"].ack,
strobe_all.eq(0)
),
self.sync += [
If(self.source.ack, strobe_all.eq(0)),
If(load_part,
Case(demux, cases),
If(demux == (self.n - 1),
If(demux == (n - 1),
demux.eq(0),
strobe_all.eq(1)
).Else(
@ -96,4 +91,3 @@ class Pack(Actor):
)
)
]
return Fragment(comb, sync)

View File

@ -1,173 +1,105 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.genlib.misc import optree
from migen.genlib.record import *
class Endpoint:
def __init__(self, token):
self.token = token
if isinstance(self, Sink):
self.stb = Signal(name="stb_i")
self.ack = Signal(name="ack_o")
def _make_m2s(layout):
r = []
for f in layout:
if isinstance(f[1], (int, tuple)):
r.append((f[0], f[1], DIR_M_TO_S))
else:
self.stb = Signal(name="stb_o")
self.ack = Signal(name="ack_i")
def token_signal(self):
sigs = self.token.flatten()
assert(len(sigs) == 1)
return sigs[0]
def __hash__(self):
return id(self)
def __repr__(self):
return "<Endpoint " + str(self.token) + ">"
r.append((f[0], _make_m2s(f[1])))
return r
class _Endpoint(Record):
def __init__(self, layout):
full_layout = [
("payload", _make_m2s(layout)),
("stb", 1, DIR_M_TO_S),
("ack", 1, DIR_S_TO_M)
]
Record.__init__(self, full_layout)
class Sink(Endpoint):
def __repr__(self):
return "<Sink " + str(self.token) + ">"
class Source(_Endpoint):
def connect(self, sink):
return Record.connect(self, sink)
class Source(Endpoint):
def __repr__(self):
return "<Source " + str(self.token) + ">"
class Sink(_Endpoint):
def connect(self, source):
return source.connect(self)
class Actor(HUID):
def __init__(self, *endpoint_descriptions, endpoints=None):
HUID.__init__(self)
if endpoints is None:
self.endpoints = {}
for desc in endpoint_descriptions:
# desc: (name, Sink/Source, token layout or existing record)
if isinstance(desc[2], Record):
token = desc[2]
else:
token = Record(desc[2])
ep = desc[1](token)
self.endpoints[desc[0]] = ep
else:
self.endpoints = endpoints
self.name = None
def get_endpoints(obj, filt=_Endpoint):
if hasattr(obj, "get_endpoints") and callable(obj.get_endpoints):
return obj.get_endpoints(filt)
r = dict()
for k, v in obj.__dict__.items():
if isinstance(v, filt):
r[k] = v
return r
def get_single_ep(obj, filt):
eps = get_endpoints(obj, filt)
if len(eps) != 1:
raise ValueError("More than one endpoint")
return list(eps.items())[0]
class BinaryActor(Module):
def __init__(self, *args, **kwargs):
self.busy = Signal()
sink = get_single_ep(self, Sink)[1]
source = get_single_ep(self, Source)[1]
self.build_binary_control(sink.stb, sink.ack, source.stb, source.ack, *args, **kwargs)
def token(self, ep):
return self.endpoints[ep].token
def filter_endpoints(self, cl):
return sorted(k for k, v in self.endpoints.items() if isinstance(v, cl))
def sinks(self):
return self.filter_endpoints(Sink)
def sources(self):
return self.filter_endpoints(Source)
def single_sink(self):
eps = self.sinks()
assert(len(eps) == 1)
return eps[0]
def single_source(self):
eps = self.sources()
assert(len(eps) == 1)
return eps[0]
def get_control_fragment(self):
raise NotImplementedError("Actor classes must overload get_control_fragment or get_fragment")
def get_process_fragment(self):
raise NotImplementedError("Actor classes must overload get_process_fragment or get_fragment")
def get_fragment(self):
return self.get_control_fragment() + self.get_process_fragment()
def __repr__(self):
r = "<" + self.__class__.__name__
if self.name is not None:
r += ": " + self.name
r += ">"
return r
class BinaryActor(Actor):
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
raise NotImplementedError("Binary actor classes must overload get_binary_control_fragment")
def get_control_fragment(self):
def get_single_ep(l):
if len(l) != 1:
raise ValueError("Binary actors have exactly one sink and one source. Consider using plumbing actors.")
return self.endpoints[l[0]]
sink = get_single_ep(self.sinks())
source = get_single_ep(self.sources())
return self.get_binary_control_fragment(sink.stb, sink.ack, source.stb, source.ack)
def build_binary_control(self, stb_i, ack_o, stb_o, ack_i):
raise NotImplementedError("Binary actor classes must overload build_binary_control_fragment")
class CombinatorialActor(BinaryActor):
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
return Fragment([stb_o.eq(stb_i), ack_o.eq(ack_i), self.busy.eq(0)])
def build_binary_control(self, stb_i, ack_o, stb_o, ack_i):
self.comb += [stb_o.eq(stb_i), ack_o.eq(ack_i), self.busy.eq(0)]
class SequentialActor(BinaryActor):
def __init__(self, delay, *endpoint_descriptions, **misc):
self.delay = delay
def __init__(self, delay):
self.trigger = Signal()
BinaryActor.__init__(self, *endpoint_descriptions, **misc)
BinaryActor.__init__(self, delay)
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
def build_binary_control(self, stb_i, ack_o, stb_o, ack_i, delay):
ready = Signal()
timer = Signal(max=self.delay+1)
comb = [ready.eq(timer == 0)]
sync = [
If(self.trigger,
timer.eq(self.delay)
timer = Signal(max=delay+1)
self.comb += ready.eq(timer == 0)
self.sync += If(self.trigger,
timer.eq(delay)
).Elif(~ready,
timer.eq(timer - 1)
)
]
mask = Signal()
comb += [
self.comb += [
stb_o.eq(ready & mask),
self.trigger.eq(stb_i & (ack_i | ~mask) & ready),
ack_o.eq(self.trigger),
busy.eq(~ready)
self.busy.eq(~ready)
]
sync += [
self.sync += [
If(self.trigger, mask.eq(1)),
If(stb_o & ack_i, mask.eq(0))
]
return Fragment(comb, sync)
class PipelinedActor(BinaryActor):
def __init__(self, latency, *endpoint_descriptions, **misc):
self.latency = latency
def __init__(self, latency):
self.pipe_ce = Signal()
BinaryActor.__init__(self, *endpoint_descriptions, **misc)
BinaryActor.__init__(self, latency)
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
valid = Signal(self.latency)
if self.latency > 1:
sync = [If(self.pipe_ce, valid.eq(Cat(stb_i, valid[:self.latency-1])))]
def build_binary_control(self, stb_i, ack_o, stb_o, ack_i, latency):
valid = Signal(latency)
if latency > 1:
self.sync += If(self.pipe_ce, valid.eq(Cat(stb_i, valid[:latency-1])))
else:
sync = [If(self.pipe_ce, valid.eq(stb_i))]
last_valid = valid[self.latency-1]
comb = [
self.sync += If(self.pipe_ce, valid.eq(stb_i))
last_valid = valid[latency-1]
self.comb += [
self.pipe_ce.eq(ack_i | ~last_valid),
ack_o.eq(self.pipe_ce),
stb_o.eq(last_valid),
self.busy.eq(optree("|", [valid[i] for i in range(self.latency)]))
self.busy.eq(optree("|", [valid[i] for i in range(latency)]))
]
return Fragment(comb, sync)
def get_conn_fragment(source, sink):
assert isinstance(source, Source)
assert isinstance(sink, Sink)
sigs_source = source.token.flatten()
sigs_sink = sink.token.flatten()
comb = [
source.ack.eq(sink.ack),
sink.stb.eq(source.stb),
Cat(*sigs_sink).eq(Cat(*sigs_source))
]
return Fragment(comb)

View File

@ -30,7 +30,7 @@ class DFGHook(Module):
def __init__(self, dfg, create):
assert(not dfg.is_abstract())
self.nodepair_to_ep = defaultdict(dict)
for hookn, (u, v, data) in dfg.edges_iter(data=True):
for hookn, (u, v, data) in enumerate(dfg.edges_iter(data=True)):
ep_to_hook = self.nodepair_to_ep[(u, v)]
ep = data["source"]
h = create(u, ep, v)

View File

@ -4,15 +4,13 @@ from migen.fhdl.structure import *
from migen.genlib.misc import optree
from migen.flow.actor import *
from migen.flow import plumbing
from migen.flow.isd import DFGReporter
# Abstract actors mean that the actor class should be instantiated with the parameters
# from the dictionary. They are needed to enable actor duplication or sharing during
# elaboration, and automatic parametrization of plumbing actors.
class AbstractActor(HUID):
class AbstractActor:
def __init__(self, actor_class, parameters=dict(), name=None):
HUID.__init__(self)
self.actor_class = actor_class
self.parameters = parameters
self.name = name
@ -27,6 +25,7 @@ class AbstractActor(HUID):
r += ">"
return r
# TODO: rewrite this without networkx and without non-determinism
class DataFlowGraph(MultiDiGraph):
def __init__(self):
MultiDiGraph.__init__(self)
@ -35,8 +34,6 @@ class DataFlowGraph(MultiDiGraph):
def add_connection(self, source_node, sink_node,
source_ep=None, sink_ep=None, # default: assume nodes have 1 source/sink and use that one
source_subr=None, sink_subr=None): # default: use whole record
assert(isinstance(source_node, (Actor, AbstractActor)))
assert(isinstance(sink_node, (Actor, AbstractActor)))
self.add_edge(source_node, sink_node,
source=source_ep, sink=sink_ep,
source_subr=source_subr, sink_subr=sink_subr)
@ -158,7 +155,7 @@ class DataFlowGraph(MultiDiGraph):
continue
other_ep = data["source"]
if other_ep is None:
other_ep = other.single_source()
other_ep = get_single_ep(other, Source)[1]
elif a.actor_class in plumbing.layout_source:
edges = self.out_edges(a, data=True)
assert(len(edges) == 1)
@ -167,10 +164,10 @@ class DataFlowGraph(MultiDiGraph):
continue
other_ep = data["sink"]
if other_ep is None:
other_ep = other.single_sink()
other_ep = get_single_ep(other, Sink)[1]
else:
raise AssertionError
layout = other.token(other_ep).layout
layout = other_ep.payload.layout
a.parameters["layout"] = layout
self.instantiate(a)
@ -184,9 +181,9 @@ class DataFlowGraph(MultiDiGraph):
# 3. resolve default eps
for u, v, d in self.edges_iter(data=True):
if d["source"] is None:
d["source"] = u.single_source()
d["source"] = get_single_ep(u, Source)[0]
if d["sink"] is None:
d["sink"] = v.single_sink()
d["sink"] = get_single_ep(v, Sink)[0]
# Elaboration turns an abstract DFG into a physical one.
# Pass 1: eliminate subrecords and divergences
@ -203,29 +200,14 @@ class DataFlowGraph(MultiDiGraph):
optimizer(self)
self._instantiate_actors()
class CompositeActor(Actor):
def __init__(self, dfg, debugger=False, debugger_nbits=48):
class CompositeActor(Module):
def __init__(self, dfg):
dfg.elaborate()
self.dfg = dfg
if debugger:
self.debugger = DFGReporter(self.dfg, debugger_nbits)
Actor.__init__(self)
def get_csrs(self):
if hasattr(self, "debugger"):
return self.debugger.get_csrs()
else:
return []
def get_fragment(self):
comb = [self.busy.eq(optree("|", [node.busy for node in self.dfg]))]
fragment = Fragment(comb)
for node in self.dfg:
fragment += node.get_fragment()
for u, v, d in self.dfg.edges_iter(data=True):
ep_src = u.endpoints[d["source"]]
ep_dst = v.endpoints[d["sink"]]
fragment += get_conn_fragment(ep_src, ep_dst)
if hasattr(self, "debugger"):
fragment += self.debugger.get_fragment()
return fragment
self.busy = Signal()
self.comb += [self.busy.eq(optree("|", [node.busy for node in dfg]))]
for node in dfg:
self.submodules += node
for u, v, d in dfg.edges_iter(data=True):
ep_src = getattr(u, d["source"])
ep_dst = getattr(v, d["sink"])
self.comb += ep_src.connect(ep_dst)

View File

@ -39,7 +39,7 @@ class EndpointReporter(EndpointSimHook):
class DFGReporter(DFGHook):
def __init__(self, dfg):
DFGHook.__init__(self, dfg, lambda u, ep, v: EndpointReporter(u.endpoints[ep]))
DFGHook.__init__(self, dfg, lambda u, ep, v: EndpointReporter(getattr(u, ep)))
def get_edge_labels(self):
d = dict()

View File

@ -6,54 +6,52 @@ from migen.genlib.misc import optree
class Buffer(PipelinedActor):
def __init__(self, layout):
PipelinedActor.__init__(self, 1,
("d", Sink, layout), ("q", Source, layout))
def get_process_fragment(self):
sigs_d = self.token("d").flatten()
sigs_q = self.token("q").flatten()
sync = [If(self.pipe_ce, Cat(*sigs_q).eq(Cat(*sigs_d)))]
return Fragment(sync=sync)
self.d = Sink(layout)
self.q = Source(layout)
PipelinedActor.__init__(self, 1)
self.sync += If(self.pipe_ce, self.q.payload.eq(self.d.payload))
class Combinator(Module, Actor):
class Combinator(Module):
def __init__(self, layout, subrecords):
eps = [("source", Source, layout)]
eps += [("sink"+str(n), Sink, layout_partial(layout, r))
for n, r in enumerate(subrecords)]
Actor.__init__(self, *eps)
self.source = Source(layout)
sinks = []
for n, r in enumerate(subrecords):
s = Sink(layout_partial(layout, *r))
setattr(self, "sink"+str(n), s)
sinks.append(s)
self.busy = Signal()
###
source = self.endpoints["source"]
sinks = [self.endpoints["sink"+str(n)]
for n in range(len(self.endpoints)-1)]
self.comb += [source.stb.eq(optree("&", [sink.stb for sink in sinks]))]
self.comb += [sink.ack.eq(source.ack & source.stb) for sink in sinks]
self.comb += [source.token.eq(sink.token) for sink in sinks]
self.comb += [
self.busy.eq(0),
self.source.stb.eq(optree("&", [sink.stb for sink in sinks]))
]
self.comb += [sink.ack.eq(self.source.ack & self.source.stb) for sink in sinks]
self.comb += [self.source.payload.eq(sink.payload) for sink in sinks]
class Splitter(Module, Actor):
class Splitter(Module):
def __init__(self, layout, subrecords):
eps = [("sink", Sink, layout)]
eps += [("source"+str(n), Source, layout_partial(layout, *r))
for n, r in enumerate(subrecords)]
Actor.__init__(self, *eps)
self.sink = Sink(layout)
sources = []
for n, r in enumerate(subrecords):
s = Source(layout_partial(layout, *r))
setattr(self, "source"+str(n), s)
sources.append(s)
self.busy = Signal()
###
sources = [self.endpoints[e] for e in self.sources()]
sink = self.endpoints[self.sinks()[0]]
self.comb += [source.token.eq(sink.token) for source in sources]
self.comb += [source.payload.eq(self.sink.payload) for source in sources]
already_acked = Signal(len(sources))
self.sync += If(sink.stb,
self.sync += If(self.sink.stb,
already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),
If(sink.ack, already_acked.eq(0))
If(self.sink.ack, already_acked.eq(0))
)
self.comb += sink.ack.eq(optree("&",
self.comb += self.sink.ack.eq(optree("&",
[s.ack | already_acked[n] for n, s in enumerate(sources)]))
for n, s in enumerate(sources):
self.comb += s.stb.eq(sink.stb & ~already_acked[n])
self.comb += s.stb.eq(self.sink.stb & ~already_acked[n])
# Actors whose layout should be inferred from what their single sink is connected to.
layout_sink = {Buffer, Splitter}

View File

@ -34,7 +34,7 @@ def layout_get(layout, name):
for f in layout:
if f[0] == name:
return f
raise KeyError
raise KeyError(name)
def layout_partial(layout, *elements):
r = []

View File

@ -17,7 +17,7 @@ class Pytholite(UnifiedIOObject):
if dataflow is not None:
self.busy.reset = 1
self.memory_ports = dict((mem, mem.get_port(write_capable=True, we_granularity=8))
for mem in self._memories)
for mem in self.buses.values() if isinstance(mem, Memory))
def get_fragment(self):
return UnifiedIOObject.get_fragment(self) + self.fragment
@ -39,7 +39,7 @@ class _TokenPullExprCompiler(ExprCompiler):
if not isinstance(node.slice, ast.Index):
raise NotImplementedError
field = ast.literal_eval(node.slice.value)
signal = getattr(self.ep.token, field)
signal = getattr(self.ep.payload, field)
return signal
@ -47,7 +47,7 @@ def _gen_df_io(compiler, modelname, to_model, from_model):
epname = ast.literal_eval(to_model["endpoint"])
values = to_model["value"]
idle_wait = ast.literal_eval(to_model["idle_wait"])
ep = compiler.ioo.endpoints[epname]
ep = getattr(compiler.ioo, epname)
if idle_wait:
state = [compiler.ioo.busy.eq(0)]
else:
@ -76,7 +76,7 @@ def _gen_df_io(compiler, modelname, to_model, from_model):
raise NotImplementedError
for akey, value in zip(values.keys, values.values):
key = ast.literal_eval(akey)
signal = getattr(ep.token, key)
signal = getattr(ep.payload, key)
state.append(signal.eq(compiler.ec.visit_expr(value)))
state += [
ep.stb.eq(1),

View File

@ -7,15 +7,14 @@ from migen.bus import wishbone, memory
from migen.bus.transactions import *
from migen.uio.trampoline import Trampoline
class UnifiedIOObject(Actor):
class UnifiedIOObject(Module):
def __init__(self, dataflow=None, buses={}):
if dataflow is not None:
Actor.__init__(self, *dataflow)
self.busy = Signal()
for name, cl, layout in dataflow:
setattr(self, name, cl(layout))
self.buses = buses
self._memories = set(v for v in self.buses.values() if isinstance(v, Memory))
def get_fragment(self):
return Fragment(specials=self._memories)
self.specials += set(v for v in self.buses.values() if isinstance(v, Memory))
(_WAIT_COMPLETE, _WAIT_POLL) = range(2)
@ -24,12 +23,12 @@ class UnifiedIOSimulation(UnifiedIOObject):
self.generator = Trampoline(generator)
UnifiedIOObject.__init__(self, dataflow, buses)
self.callers = []
callers = []
self.busname_to_caller_id = {}
if dataflow is not None:
self.callers.append(TokenExchanger(self.dispatch_g(0), self))
callers.append(TokenExchanger(self.dispatch_g(0), self))
for k, v in self.buses.items():
caller_id = len(self.callers)
caller_id = len(callers)
self.busname_to_caller_id[k] = caller_id
g = self.dispatch_g(caller_id)
if isinstance(v, wishbone.Interface):
@ -38,7 +37,8 @@ class UnifiedIOSimulation(UnifiedIOObject):
caller = memory.Initiator(g, v)
else:
raise NotImplementedError
self.callers.append(caller)
callers.append(caller)
self.submodules += callers
self.dispatch_state = _WAIT_COMPLETE
self.dispatch_caller = 0
@ -75,7 +75,3 @@ class UnifiedIOSimulation(UnifiedIOObject):
yield self.pending_transaction
else:
yield None
def get_fragment(self):
f = UnifiedIOObject.get_fragment(self)
return sum([c.get_fragment() for c in self.callers], f)