flow: use Module and new Record APIs
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 10 Apr 2013 17:12:42 +0000 (19:12 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 10 Apr 2013 17:12:42 +0000 (19:12 +0200)
20 files changed:
examples/dataflow/dma.py
examples/dataflow/misc.py
examples/dataflow/structuring.py
examples/pytholite/basic.py
examples/pytholite/uio.py
examples/sim/dataflow.py
migen/actorlib/dma_asmi.py
migen/actorlib/dma_wishbone.py
migen/actorlib/misc.py
migen/actorlib/sim.py
migen/actorlib/spi.py
migen/actorlib/structuring.py
migen/flow/actor.py
migen/flow/hooks.py
migen/flow/network.py
migen/flow/perftools.py
migen/flow/plumbing.py
migen/genlib/record.py
migen/pytholite/io.py
migen/uio/ioo.py

index 322a61954d3970550a851edbd47de4ef9ec56a1a..38d77300afc94aa7f3cc1a324d43024c3d710350 100644 (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()
-
-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()
index 14a6aa780778978695191622a11c2ba8aef04d41..bb1df5b4b5c3748f377c86c68054c690beb470b3 100644 (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()
index 4d2696113244d9b2348aaf410b45af4545ddcd54..7f3014682908c7ed154a00e1a4e3fd5d54a08541 100644 (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)]
-       
-       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()
index c1b4b7805e93e8105fbfc0ee4593a6d4f5ce1057..621e61c946d5d14363993cf70b30a09d78ebe696 100644 (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()
index 9499200e84273f179412e444ae9fb49cda2a2b9a..3718acc2a6a0ab2f2c34f1a9cd4d0a7febd67b24 100644 (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()
index 8e2628c81af820d1a43939dc9f28544d444590f2..4c02b24fd9b04d4b6ff207cef9d110c2cea3d570 100644 (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())
+
+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()
index 65d05ca8dc0189965f2c5319da898a8fe36886a3..9ff46dedb307e50a10c1f1d98a9cd8abeb3d7bbf 100644 (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)
index d316a372a7698cbd980fde1a814be60d9ae71eb9..c3551a3b35813e52ac8c95feb91d1885c3f14c55 100644 (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)
index b0799706c162d5d3bec9d0c1a21e60756de102a5..f1d95acb62607b60a1dd2f1d9fec3be81565b3be 100644 (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()
index 78abbeef19224487b6f9b95d57d51cff76b38e5d..8c6463b451de1487858c2dd2008c704bbe9df6e8 100644 (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))
index 7b94fe45b13502755509ee6e3085fd83dcb77670..733e928a3350a3fa681186729167789b87cb7ac5 100644 (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})
index 0041806d07f5b847ac2e6a1570ddfd6043f5c2d0..dd917bbc26de8790b5106813bf75512c7d9c508b 100644 (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)
index 867a5009666bb8f5f3547bbac3f7efcbee361edb..2d7e134c628eb5d2d97f7b2b3c7fcab262a97a6c 100644 (file)
 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)
index 82ae60a58bd69315f244659f2b7453bccab0bfa1..7c20a0eb0fe81b333a196fd55d88deebf91f60aa 100644 (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)
index 4f222143a2ea89aa4f837fff681fe5b64c9120f4..a9970a74ad089397ca84c9493a11e6ced437b3f4 100644 (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)
index ff4dcb8a915499b3f735bee3fdbb32d87b91bbf4..9bb373392b602d0758d636a6b6254f3ef9cb4bd3 100644 (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()
index d19abc077eddb975a1e02a0fcf7d5bc8b8300e1e..8edec896193cac46b8f1d54b0131da2bdcc65ba6 100644 (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}
index f1a22c7061791e0be1d93ba766de1726fbc688c1..4d790647540d71612294299c04f51a2e8befba32 100644 (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 = []
index 63c92a60b9efe7e8a77c86cc1c52bce4c0cce1f9..c20cc467a3692cbc32a554ab0e60f98b5c72231f 100644 (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),
index e6c954b5592cb88efbbf6815f899da28399a37f0..e618c2c62a7da57a0fdce7ecdda59130fc8a2613 100644 (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)