From d2d55372d8694cf164905b8c8f98268e03871342 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 8 Jan 2012 13:56:11 +0100 Subject: [PATCH] Composer (WIP) --- examples/dataflow.py | 17 ++++----- migen/corelogic/record.py | 6 ++-- migen/flow/actor.py | 16 ++++++--- migen/flow/ala.py | 56 +++++++++++++++++++++++++---- migen/flow/composer.py | 75 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 25 deletions(-) create mode 100644 migen/flow/composer.py diff --git a/examples/dataflow.py b/examples/dataflow.py index f32f155ed..7707b3a2d 100644 --- a/examples/dataflow.py +++ b/examples/dataflow.py @@ -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() diff --git a/migen/corelogic/record.py b/migen/corelogic/record.py index 52b20c4fa..3e293825e 100644 --- a/migen/corelogic/record.py +++ b/migen/corelogic/record.py @@ -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 = [] diff --git a/migen/flow/actor.py b/migen/flow/actor.py index 6110c406d..344243147 100644 --- a/migen/flow/actor.py +++ b/migen/flow/actor.py @@ -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 "" 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))] diff --git a/migen/flow/ala.py b/migen/flow/ala.py index 1fc53bb34..c9ddfb8e2 100644 --- a/migen/flow/ala.py +++ b/migen/flow/ala.py @@ -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 Divider(Actor): +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 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 index 000000000..3a8f00e67 --- /dev/null +++ b/migen/flow/composer.py @@ -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