Composer (WIP)
This commit is contained in:
parent
34c69db14a
commit
d2d55372d8
|
@ -2,20 +2,15 @@ import networkx as nx
|
||||||
|
|
||||||
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()
|
||||||
|
|
|
@ -60,9 +60,9 @@ class Record:
|
||||||
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 = []
|
||||||
|
|
|
@ -28,6 +28,12 @@ class Endpoint:
|
||||||
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)
|
||||||
|
|
||||||
|
@ -145,8 +151,8 @@ class Actor:
|
||||||
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)
|
||||||
|
@ -154,9 +160,9 @@ def get_conn_control_fragment(source, sink):
|
||||||
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))]
|
||||||
|
|
|
@ -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 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):
|
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)])
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue