Remove ActorNode
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 12 Dec 2012 21:20:48 +0000 (22:20 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 12 Dec 2012 21:20:48 +0000 (22:20 +0100)
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/flow/actor.py
migen/flow/network.py

index 5bcd063ed5accaefab4415bd0a9c6d8ad89c313a..8e221edcce599c31bd0f32632c5b1f97dbe5967c 100644 (file)
@@ -1,7 +1,6 @@
 from random import Random
 
 from migen.flow.network import *
-from migen.actorlib.ala import *
 from migen.actorlib import dma_wishbone, dma_asmi
 from migen.actorlib.sim import *
 from migen.bus import wishbone, asmibus
@@ -43,7 +42,7 @@ def trgen_gen():
 def wishbone_sim(efragment, master, end_simulation):
        peripheral = wishbone.Target(MyModelWB())
        tap = wishbone.Tap(peripheral.bus)
-       interconnect = wishbone.InterconnectPointToPoint(master.actor.bus, peripheral.bus)
+       interconnect = wishbone.InterconnectPointToPoint(master.bus, peripheral.bus)
        def _end_simulation(s):
                s.interrupt = end_simulation(s)
        fragment = efragment \
@@ -70,27 +69,27 @@ def asmi_sim(efragment, hub, end_simulation):
 
 def test_wb_reader():
        print("*** Testing Wishbone reader")
-       adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", 30)])))
-       reader = ActorNode(dma_wishbone.Reader())
-       dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", 32)])))
+       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.actor.token_exchanger.done and not s.rd(comp.busy))
+               lambda s: adrgen.token_exchanger.done and not s.rd(comp.busy))
 
 def test_wb_writer():
        print("*** Testing Wishbone writer")
-       trgen = ActorNode(SimActor(trgen_gen(), ("address_data", Source, [("a", 30), ("d", 32)])))
-       writer = ActorNode(dma_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.actor.token_exchanger.done and not s.rd(comp.busy))
+               lambda s: trgen.token_exchanger.done and not s.rd(comp.busy))
 
 def test_asmi_reader(nslots):
        print("*** Testing ASMI reader (nslots={})".format(nslots))
@@ -99,16 +98,16 @@ def test_asmi_reader(nslots):
        port = hub.get_port(nslots)
        hub.finalize()
        
-       adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", 32)])))
-       reader = ActorNode(dma_asmi.Reader(port))
-       dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", 32)])))
+       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.actor.token_exchanger.done and not s.rd(comp.busy))
+               lambda s: adrgen.token_exchanger.done and not s.rd(comp.busy))
 
 test_wb_reader()
 test_wb_writer()
index 71e0f2486f77238ad8232a555ad8511def9d5696..a4dc71d6f4ee93753a13bde9656a4ecfdbd114d0 100644 (file)
@@ -17,9 +17,9 @@ def sink_gen():
                print(t.value["value"])
 
 def main():
-       source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", 32)])))
-       loop = ActorNode(misc.IntSequence(32))
-       sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", 32)])))
+       source = SimActor(source_gen(), ("source", Source, [("value", 32)]))
+       loop = misc.IntSequence(32)
+       sink = SimActor(sink_gen(), ("sink", Sink, [("value", 32)]))
        g = DataFlowGraph()
        g.add_connection(source, loop)
        g.add_connection(loop, sink)
index fdbc75340cec29f63678d186e7c2e6e9d891976f..2a6dd24e172aba4ba38111fcac27898f9eac823d 100644 (file)
@@ -27,14 +27,14 @@ def main():
        packed_layout = structuring.pack_layout(base_layout, pack_factor)
        rawbits_layout = [("value", 32*pack_factor)]
        
-       source = ActorNode(SimActor(source_gen(), ("source", Source, base_layout)))
-       sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, base_layout)))
+       source = SimActor(source_gen(), ("source", Source, base_layout))
+       sink = SimActor(sink_gen(), ("sink", Sink, base_layout))
        
        # A tortuous way of passing integer tokens.
-       packer = ActorNode(structuring.Pack(base_layout, pack_factor))
-       to_raw = ActorNode(structuring.Cast(packed_layout, rawbits_layout))
-       from_raw = ActorNode(structuring.Cast(rawbits_layout, packed_layout))
-       unpacker = ActorNode(structuring.Unpack(pack_factor, base_layout))
+       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)
index d2df3df39ed8da576ea8c93d403191099495f11c..921b0e5e2051a602f67af7ecbc3840e7a768dac3 100644 (file)
@@ -14,7 +14,7 @@ def number_gen():
 def run_sim(ng):
        g = DataFlowGraph()
        d = Dumper(layout)
-       g.add_connection(ActorNode(ng), ActorNode(d))
+       g.add_connection(ng, d)
        
        c = CompositeActor(g)
        fragment = c.get_fragment()
index ed8e92684ee3c5ec79639c0569ccd02efaebb743..1a0690cdc78d5a3062670cd35e26775a30bc2a3e 100644 (file)
@@ -31,7 +31,7 @@ class SlaveModel(wishbone.TargetModel):
 def run_sim(ng):
        g = DataFlowGraph()
        d = Dumper(layout)
-       g.add_connection(ActorNode(ng), ActorNode(d))
+       g.add_connection(ng, d)
        
        slave = wishbone.Target(SlaveModel())
        intercon = wishbone.InterconnectPointToPoint(ng.buses["wb"], slave.bus)
index 2137620ffb996add2187092291bde30f89091093..318206a25bac2d452d2f00706a6e461b5ec9bc04 100644 (file)
@@ -17,13 +17,13 @@ def sink_gen():
                print("Received: " + str(t.value["value"]))
 
 def main():
-       source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", 32)])))
-       sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", 32)])))
+       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.actor.token_exchanger.done
+               s.interrupt = source.token_exchanger.done
        fragment = comp.get_fragment() + Fragment(sim=[end_simulation])
        sim = Simulator(fragment, Runner())
        sim.run()
index 5552624cfa1becbf9ab93142f1557b847ee7cedb..fd9fd20b72dc4e7339c6f5fc7245978f0ea666a4 100644 (file)
@@ -32,8 +32,9 @@ class Source(Endpoint):
        def __repr__(self):
                return "<Source " + str(self.token) + ">"
 
-class Actor:
+class Actor(HUID):
        def __init__(self, *endpoint_descriptions, endpoints=None):
+               super().__init__()
                if endpoints is None:
                        self.endpoints = {}
                        for desc in endpoint_descriptions:
index acbbb6adb33a524d3452cef90269d1d3bb6982c9..c26af1f3add61ec83696d157b3ab4631ebd07bbf 100644 (file)
@@ -6,57 +6,37 @@ from migen.flow.actor import *
 from migen.flow import plumbing
 from migen.flow.isd import DFGReporter
 
-# Graph nodes can be either:
-#  (1) a reference to an existing actor
-#  (2) an abstract (class, dictionary) pair meaning that the actor class should be
-#      instantiated with the parameters from the dictionary.
-#      This form is needed to enable actor duplication or sharing during elaboration.
+# 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 ActorNode(HUID):
-       def __init__(self, actor_class, parameters=dict()):
+class AbstractActor(HUID):
+       def __init__(self, actor_class, parameters=dict(), name=None):
                super().__init__()
-               if isinstance(actor_class, type):
-                       self.actor_class = actor_class
-                       self.parameters = parameters
-               else:
-                       self.actor = actor_class
-               self.name = None
+               self.actor_class = actor_class
+               self.parameters = parameters
+               self.name = name
        
-       def is_abstract(self):
-               return hasattr(self, "actor_class")
-               
-       def instantiate(self):
-               self.actor = self.actor_class(**self.parameters)
-               self.actor.name = self.name
-               del self.actor_class
-               del self.parameters
-       
-       def get_dict(self):
-               if self.is_abstract():
-                       return self.parameters
-               else:
-                       return self.actor.__dict__
+       def create_instance(self):
+               return self.actor_class(**self.parameters)
        
        def __repr__(self):
-               if self.is_abstract():
-                       r = "<abstract " + self.actor_class.__name__
-                       if self.name is not None:
-                               r += ": " + self.name
-                       r += ">"
-               else:
-                       r = repr(self.actor)
+               r = "<abstract " + self.actor_class.__name__
+               if self.name is not None:
+                       r += ": " + self.name
+               r += ">"
                return r
 
 class DataFlowGraph(MultiDiGraph):
        def __init__(self):
-               self.elaborated = False
                super().__init__()
+               self.elaborated = False
        
        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, ActorNode))
-               assert(isinstance(sink_node, ActorNode))
+               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)
@@ -74,6 +54,17 @@ class DataFlowGraph(MultiDiGraph):
                for key in edges_to_delete:
                        self.remove_edge(source_node, sink_node, key)
        
+       def replace_actor(self, old, new):
+               self.add_node(new)
+               for xold, v, data in self.out_edges(old, data=True):
+                       self.add_edge(new, v, **data)
+               for u, xold, data in self.in_edges(old, data=True):
+                       self.add_edge(u, new, **data)
+               self.remove_node(old)
+               
+       def instantiate(self, actor):
+               self.replace_actor(actor, actor.create_instance())
+       
        # Returns a dictionary
        #   source -> [sink1, ..., sinkn]
        # source element is a (node, endpoint) pair.
@@ -116,7 +107,7 @@ class DataFlowGraph(MultiDiGraph):
        # NB: It is not allowed for a single sink to be fed by more than one source
        # (except with subrecords, i.e. when a combinator is used)
        def is_abstract(self):
-               return any(x.is_abstract() for x in self) \
+               return any(isinstance(x, AbstractActor) for x in self) \
                        or any(d["source_subr"] is not None or d["sink_subr"] is not None
                                for u, v, d in self.edges_iter(data=True)) \
                        or bool(self._list_divergences())
@@ -128,7 +119,7 @@ class DataFlowGraph(MultiDiGraph):
                                # build combinator
                                # "layout" is filled in during instantiation
                                subrecords = [dst_subrecord for src_node, src_endpoint, dst_subrecord, src_subrecord in sources]
-                               combinator = ActorNode(plumbing.Combinator, {"subrecords": subrecords})
+                               combinator = AbstractActor(plumbing.Combinator, {"subrecords": subrecords})
                                # disconnect source1 -> sink ... sourcen -> sink
                                # connect source1 -> combinator_sink1 ... sourcen -> combinator_sinkn
                                for n, (src_node, src_endpoint, dst_subrecord, src_subrecord) in enumerate(sources):
@@ -142,7 +133,7 @@ class DataFlowGraph(MultiDiGraph):
                for (src_node, src_endpoint), sinks in self._source_to_sinks().items():
                        if len(sinks) > 1 or sinks[0][2] is not None:
                                subrecords = [src_subrecord for dst_node, dst_endpoint, src_subrecord, dst_subrecord in sinks]
-                               splitter = ActorNode(plumbing.Splitter, {"subrecords": subrecords})
+                               splitter = AbstractActor(plumbing.Splitter, {"subrecords": subrecords})
                                # disconnect source -> sink1 ... source -> sinkn
                                # connect splitter_source1 -> sink1 ... splitter_sourcen -> sinkn
                                for n, (dst_node, dst_endpoint, src_subrecord, dst_subrecord) in enumerate(sinks):
@@ -155,7 +146,7 @@ class DataFlowGraph(MultiDiGraph):
        
        def _infer_plumbing_layout(self):
                while True:
-                       ap = [a for a in self if a.is_abstract() and a.actor_class in plumbing.actors]
+                       ap = [a for a in self if isinstance(a, AbstractActor) and a.actor_class in plumbing.actors]
                        if not ap:
                                break
                        for a in ap:
@@ -167,7 +158,7 @@ class DataFlowGraph(MultiDiGraph):
                                                continue
                                        other_ep = data["source"]
                                        if other_ep is None:
-                                               other_ep = other.actor.single_source()
+                                               other_ep = other.single_source()
                                elif a.actor_class in plumbing.layout_source:
                                        edges = self.out_edges(a, data=True)
                                        assert(len(edges) == 1)
@@ -176,26 +167,26 @@ class DataFlowGraph(MultiDiGraph):
                                                continue
                                        other_ep = data["sink"]
                                        if other_ep is None:
-                                               other_ep = other.actor.single_sink()
+                                               other_ep = other.single_sink()
                                else:
                                        raise AssertionError
-                               layout = other.actor.token(other_ep).layout()
+                               layout = other.token(other_ep).layout()
                                a.parameters["layout"] = layout
-                               a.instantiate()
+                               self.instantiate(a)
        
        def _instantiate_actors(self):
                # 1. instantiate all abstract non-plumbing actors
-               for actor in self:
-                       if actor.is_abstract() and actor.actor_class not in plumbing.actors:
-                               actor.instantiate()
+               for actor in list(self):
+                       if isinstance(actor, AbstractActor) and actor.actor_class not in plumbing.actors:
+                               self.instantiate(actor)
                # 2. infer plumbing layout and instantiate plumbing
                self._infer_plumbing_layout()
                # 3. resolve default eps
                for u, v, d in self.edges_iter(data=True):
                        if d["source"] is None:
-                               d["source"] = u.actor.single_source()
+                               d["source"] = u.single_source()
                        if d["sink"] is None:
-                               d["sink"] = v.actor.single_sink()
+                               d["sink"] = v.single_sink()
        
        # Elaboration turns an abstract DFG into a physical one.
        #   Pass 1: eliminate subrecords and divergences
@@ -227,13 +218,13 @@ class CompositeActor(Actor):
                        return []
        
        def get_fragment(self):
-               comb = [self.busy.eq(optree("|", [node.actor.busy for node in self.dfg]))]
+               comb = [self.busy.eq(optree("|", [node.busy for node in self.dfg]))]
                fragment = Fragment(comb)
                for node in self.dfg:
-                       fragment += node.actor.get_fragment()
+                       fragment += node.get_fragment()
                for u, v, d in self.dfg.edges_iter(data=True):
-                       ep_src = u.actor.endpoints[d["source"]]
-                       ep_dst = v.actor.endpoints[d["sink"]]
+                       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()