Composer (WIP)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 8 Jan 2012 12:56:11 +0000 (13:56 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 8 Jan 2012 12:56:11 +0000 (13:56 +0100)
examples/dataflow.py
migen/corelogic/record.py
migen/flow/actor.py
migen/flow/ala.py
migen/flow/composer.py [new file with mode: 0644]

index f32f155ed14ca0d270d5d8df1e6172f96b290362..7707b3a2dc64aa312ff92ed11854aef4f21bc3ce 100644 (file)
@@ -2,20 +2,15 @@ import networkx as nx
 
 from migen.fhdl import verilog 
 from migen.flow.ala import *
-from migen.flow.plumbing import *
 from migen.flow.network import *
-
-def get_actor_fragments(*actors):
-       return sum([a.get_control_fragment() + a.get_process_fragment() for a in actors], Fragment())
-
-act = Adder(32)
-comb = Combinator(act.operands.template(), ["a"], ["b"])
-outbuf = Buffer(act.result.template())
+from migen.flow.composer import *
 
 g = nx.MultiDiGraph()
-g.add_nodes_from([act, comb, outbuf])
-add_connection(g, comb, act)
-add_connection(g, act, outbuf)
+a1 = make_composable(g, Add(BV(16)))
+a2 = make_composable(g, Add(BV(16)))
+a3 = make_composable(g, Add(BV(16)))
+c3 = (a1 + a2)*a3
+print(c3)
 c = CompositeActor(g)
 
 frag = c.get_control_fragment() + c.get_process_fragment()
index 52b20c4fa473adbffe9b5bc6b01e15b4901886e5..3e293825e0bcb0885bf0b10ff9ed90e12cebf4ca 100644 (file)
@@ -60,9 +60,9 @@ class Record:
                return Record(dict_to_list(fields), "subrecord")
        
        def compatible(self, other):
-               tpl1 = self.template()
-               tpl2 = other.template()
-               return tpl1 == tpl2
+               tpl1 = self.flatten()
+               tpl2 = other.flatten()
+               return len(tpl1) == len(tpl2)
        
        def flatten(self):
                l = []
index 6110c406d65d1d4b5330d308302f73b641ff3923..344243147a054fcabfc7021bc0b9b849cd127916 100644 (file)
@@ -28,6 +28,12 @@ class Endpoint:
                else:
                        self.stb = Signal(namer="stb_o")
                        self.ack = Signal(namer="ack_i")
+       
+       def token_signal(self):
+               sigs = self.token.flatten()
+               assert(len(sigs) == 1)
+               return sigs[0]
+       
        def __hash__(self):
                return id(self)
                
@@ -145,8 +151,8 @@ class Actor:
                return "<Actor " + repr(self.scheduling_model) + " " + repr(self.sinks()) + " " + repr(self.sources()) + ">"
 
 def get_conn_control_fragment(source, sink):
-       assert(isinstance(source, Source))
-       assert(isinstance(sink, Sink))
+       assert isinstance(source, Source)
+       assert isinstance(sink, Sink)
        comb = [
                source.ack.eq(sink.ack),
                sink.stb.eq(source.stb)
@@ -154,9 +160,9 @@ def get_conn_control_fragment(source, sink):
        return Fragment(comb)
        
 def get_conn_process_fragment(source, sink):
-       assert(isinstance(source, Source))
-       assert(isinstance(sink, Sink))
-       assert(sink.token.compatible(source.token))
+       assert isinstance(source, Source)
+       assert isinstance(sink, Sink)
+       assert sink.token.compatible(source.token)
        sigs_source = source.token.flatten()
        sigs_sink = sink.token.flatten()
        comb = [Cat(*sigs_sink).eq(Cat(*sigs_source))]
index 1fc53bb348038c4302aa803cded838205b03915f..c9ddfb8e2ec80882ea000cd90060c27eed16dbc4 100644 (file)
@@ -1,20 +1,64 @@
 from migen.fhdl.structure import *
+from migen.fhdl.structure import _Operator
 from migen.flow.actor import *
 from migen.corelogic.record import *
 from migen.corelogic import divider
 
-class Adder(Actor):
-       def __init__(self, width):
-               self.operands = Record([('a', BV(width)), ('b', BV(width))])
-               self.result = Record([('sum', BV(width+1))])
+class _SimpleBinary(Actor):
+       def __init__(self, op, bv_op, bv_r):
+               self.op = op
+               self.operands = Record([('a', bv_op), ('b', bv_op)])
+               self.result = Record([('r', bv_r)])
                Actor.__init__(self,
                        SchedulingModel(SchedulingModel.COMBINATORIAL),
                        self.operands, self.result)
 
        def get_process_fragment(self):
-               return Fragment([self.result.sum.eq(self.operands.a + self.operands.b)])
+               return Fragment([
+                       self.result.r.eq(_Operator(self.op, [self.operands.a, self.operands.b]))
+               ])
+
+class Add(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '+', bv, BV(bv.width+1, bv.signed))
+
+class Sub(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '-', bv, BV(bv.width+1, bv.signed))
+
+class Mul(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '*', bv, BV(2*bv.width, bv.signed))
+
+class And(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '*', bv, bv)
+
+class Xor(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '^', bv, bv)
+
+class Or(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '|', bv, bv)
+
+class LT(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '<', bv, BV(1))
+
+class LE(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '<=', bv, BV(1))
+
+class EQ(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '==', bv, BV(1))
+
+class NE(_SimpleBinary):
+       def __init__(self, bv):
+               _SimpleBinary.__init__(self, '!=', bv, BV(1))
 
-class Divider(Actor):
+class DivMod(Actor):
        def __init__(self, width):
                self.div = divider.Inst(width)
                self.operands = Record([('dividend', self.div.dividend_i), ('divisor', self.div.divisor_i)])
diff --git a/migen/flow/composer.py b/migen/flow/composer.py
new file mode 100644 (file)
index 0000000..3a8f00e
--- /dev/null
@@ -0,0 +1,75 @@
+import networkx as nx
+
+from migen.flow.actor import *
+from migen.flow.ala import *
+from migen.flow.plumbing import *
+from migen.flow.network import *
+
+def _get_bin_sigs(a, b):
+       assert id(a.dfg) == id(b.dfg)
+       return (a.endp.token_signal(), b.endp.token_signal())
+
+def _simple_binary(a, b, actor_class):
+       (signal_self, signal_other) = _get_bin_sigs(a, b)
+       width = max(signal_self.bv.width, signal_other.bv.width)
+       signed = signal_self.bv.signed and signal_other.bv.signed
+       actor = actor_class(BV(width, signed))
+       combinator = Combinator(actor.operands.template(), ["a"], ["b"])
+       add_connection(a.dfg, combinator, actor)
+       add_connection(a.dfg, a.actor, combinator, a.endp, combinator.sinks()[0])
+       add_connection(a.dfg, b.actor, combinator, b.endp, combinator.sinks()[1])
+       return make_composable(a.dfg, actor)
+
+class ComposableSource():
+       def __init__(self, dfg, actor, endp):
+               self.dfg = dfg
+               self.actor = actor
+               self.endp = endp
+       
+       def __add__(self, other):
+               return _simple_binary(self, other, Add)
+       def __radd__(self, other):
+               return _simple_binary(other, self, Add)
+       def __sub__(self, other):
+               return _simple_binary(self, other, Sub)
+       def __rsub__(self, other):
+               return _simple_binary(other, self, Sub)
+       def __mul__(self, other):
+               return _simple_binary(self, other, Mul)
+       def __rmul__(self, other):
+               return _simple_binary(other, self, Mul)
+       def __and__(self, other):
+               return _simple_binary(self, other, And)
+       def __rand__(self, other):
+               return _simple_binary(other, self, And)
+       def __xor__(self, other):
+               return _simple_binary(self, other, Xor)
+       def __rxor__(self, other):
+               return _simple_binary(other, self, Xor)
+       def __or__(self, other):
+               return _simple_binary(self, other, Or)
+       def __ror__(self, other):
+               return _simple_binary(other, self, Or)
+
+       def __lt__(self, other):
+               return _simple_binary(self, other, LT)
+       def __le__(self, other):
+               return _simple_binary(self, other, LE)
+       def __eq__(self, other):
+               return _simple_binary(self, other, EQ)
+       def __ne__(self, other):
+               return _simple_binary(self, other, NE)
+       def __gt__(self, other):
+               return _simple_binary(other, self, LT)
+       def __ge__(self, other):
+               return _simple_binary(other, self, LE)
+
+def make_composable(dfg, actor):
+       sources = actor.sources()
+       l = [ComposableSource(dfg, actor, source) for source in sources]
+       if len(l) > 1:
+               return tuple(l)
+       elif len(l) > 0:
+               return l[0]
+       else:
+               return None