Skip to content

Commit

Permalink
Composer (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Bourdeauducq committed Jan 8, 2012
1 parent 34c69db commit d2d5537
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 25 deletions.
17 changes: 6 additions & 11 deletions examples/dataflow.py
Expand Up @@ -2,20 +2,15 @@


from migen.fhdl import verilog from migen.fhdl import verilog
from migen.flow.ala import * from migen.flow.ala import *
from migen.flow.plumbing import *
from migen.flow.network import * from migen.flow.network import *

from migen.flow.composer 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())


g = nx.MultiDiGraph() g = nx.MultiDiGraph()
g.add_nodes_from([act, comb, outbuf]) a1 = make_composable(g, Add(BV(16)))
add_connection(g, comb, act) a2 = make_composable(g, Add(BV(16)))
add_connection(g, act, outbuf) a3 = make_composable(g, Add(BV(16)))
c3 = (a1 + a2)*a3
print(c3)
c = CompositeActor(g) c = CompositeActor(g)


frag = c.get_control_fragment() + c.get_process_fragment() frag = c.get_control_fragment() + c.get_process_fragment()
Expand Down
6 changes: 3 additions & 3 deletions migen/corelogic/record.py
Expand Up @@ -60,9 +60,9 @@ def dict_to_list(d):
return Record(dict_to_list(fields), "subrecord") return Record(dict_to_list(fields), "subrecord")


def compatible(self, other): def compatible(self, other):
tpl1 = self.template() tpl1 = self.flatten()
tpl2 = other.template() tpl2 = other.flatten()
return tpl1 == tpl2 return len(tpl1) == len(tpl2)


def flatten(self): def flatten(self):
l = [] l = []
Expand Down
16 changes: 11 additions & 5 deletions migen/flow/actor.py
Expand Up @@ -28,6 +28,12 @@ def __init__(self, token):
else: else:
self.stb = Signal(namer="stb_o") self.stb = Signal(namer="stb_o")
self.ack = Signal(namer="ack_i") self.ack = Signal(namer="ack_i")

def token_signal(self):
sigs = self.token.flatten()
assert(len(sigs) == 1)
return sigs[0]

def __hash__(self): def __hash__(self):
return id(self) return id(self)


Expand Down Expand Up @@ -145,18 +151,18 @@ def __repr__(self):
return "<Actor " + repr(self.scheduling_model) + " " + repr(self.sinks()) + " " + repr(self.sources()) + ">" return "<Actor " + repr(self.scheduling_model) + " " + repr(self.sinks()) + " " + repr(self.sources()) + ">"


def get_conn_control_fragment(source, sink): def get_conn_control_fragment(source, sink):
assert(isinstance(source, Source)) assert isinstance(source, Source)
assert(isinstance(sink, Sink)) assert isinstance(sink, Sink)
comb = [ comb = [
source.ack.eq(sink.ack), source.ack.eq(sink.ack),
sink.stb.eq(source.stb) sink.stb.eq(source.stb)
] ]
return Fragment(comb) return Fragment(comb)


def get_conn_process_fragment(source, sink): def get_conn_process_fragment(source, sink):
assert(isinstance(source, Source)) assert isinstance(source, Source)
assert(isinstance(sink, Sink)) assert isinstance(sink, Sink)
assert(sink.token.compatible(source.token)) assert sink.token.compatible(source.token)
sigs_source = source.token.flatten() sigs_source = source.token.flatten()
sigs_sink = sink.token.flatten() sigs_sink = sink.token.flatten()
comb = [Cat(*sigs_sink).eq(Cat(*sigs_source))] comb = [Cat(*sigs_sink).eq(Cat(*sigs_source))]
Expand Down
56 changes: 50 additions & 6 deletions migen/flow/ala.py
@@ -1,20 +1,64 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.structure import _Operator
from migen.flow.actor import * from migen.flow.actor import *
from migen.corelogic.record import * from migen.corelogic.record import *
from migen.corelogic import divider from migen.corelogic import divider


class Adder(Actor): class _SimpleBinary(Actor):
def __init__(self, width): def __init__(self, op, bv_op, bv_r):
self.operands = Record([('a', BV(width)), ('b', BV(width))]) self.op = op
self.result = Record([('sum', BV(width+1))]) self.operands = Record([('a', bv_op), ('b', bv_op)])
self.result = Record([('r', bv_r)])
Actor.__init__(self, Actor.__init__(self,
SchedulingModel(SchedulingModel.COMBINATORIAL), SchedulingModel(SchedulingModel.COMBINATORIAL),
self.operands, self.result) self.operands, self.result)


def get_process_fragment(self): 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): def __init__(self, width):
self.div = divider.Inst(width) self.div = divider.Inst(width)
self.operands = Record([('dividend', self.div.dividend_i), ('divisor', self.div.divisor_i)]) self.operands = Record([('dividend', self.div.dividend_i), ('divisor', self.div.divisor_i)])
Expand Down
75 changes: 75 additions & 0 deletions 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

0 comments on commit d2d5537

Please sign in to comment.