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
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
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()
-
-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 SimTrGen(SimActor):
+ def __init__(self):
+ self.address_data = Source([("a", 30), ("d", 32)])
+ SimActor.__init__(self, trgen_gen())
+
+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()
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:
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()
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)]
-
- source = SimActor(source_gen(), ("source", Source, base_layout))
- sink = SimActor(sink_gen(), ("sink", Sink, base_layout))
+ tb = TB()
+ sim = Simulator(tb).run(1000)
- # 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()
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)
def main():
print("Simulating native Python:")
- ng_native = SimActor(number_gen(), ("result", Source, layout))
+ ng_native = SimNumberGen()
run_sim(ng_native)
print("Simulating Pytholite:")
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()
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()
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())
+
+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
-main()
+Simulator(TB()).run()
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)
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)
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()
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):
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
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()
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))
(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())
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,
rp.adr.eq(self._r_ra.storage),
self._r_rd.status.eq(rp.dat_r)
]
-
- return Fragment(comb, specials={mem})
from migen.fhdl.structure import *
+from migen.fhdl.module import Module
from migen.flow.actor import *
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(
)
]
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(
)
)
]
- return Fragment(comb, sync)
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) + ">"
-
-
-class Sink(Endpoint):
- def __repr__(self):
- return "<Sink " + str(self.token) + ">"
-
-class Source(Endpoint):
- def __repr__(self):
- return "<Source " + str(self.token) + ">"
-
-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
+ 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 Source(_Endpoint):
+ def connect(self, sink):
+ return Record.connect(self, sink)
+
+class Sink(_Endpoint):
+ def connect(self, source):
+ return source.connect(self)
+
+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)
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)
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
r += ">"
return r
+# TODO: rewrite this without networkx and without non-determinism
class DataFlowGraph(MultiDiGraph):
def __init__(self):
MultiDiGraph.__init__(self)
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)
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)
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)
# 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
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)
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()
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}
for f in layout:
if f[0] == name:
return f
- raise KeyError
+ raise KeyError(name)
def layout_partial(layout, *elements):
r = []
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
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
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:
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),
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)
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):
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
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)