class MultiInControlBase(Elaboratable):
""" Common functions for Pipeline API
"""
- def __init__(self, in_multi=None, p_len=1):
+ def __init__(self, in_multi=None, p_len=1, maskwid=0, routemask=False):
""" Multi-input Control class. Conforms to same API as ControlBase...
mostly. has additional indices to the *multiple* input stages
* add data_i members to PrevControl and
* add data_o member to NextControl
"""
+ self.routemask = routemask
# set up input and output IO ACK (prev/next ready/valid)
+ print ("multi_in", maskwid, p_len)
p = []
for i in range(p_len):
- p.append(PrevControl(in_multi))
+ p.append(PrevControl(in_multi, maskwid=maskwid))
self.p = Array(p)
- self.n = NextControl()
+ if routemask:
+ nmaskwid = maskwid # straight route mask mode
+ else:
+ nmaskwid = maskwid * p_len # fan-in mode
+ self.n = NextControl(maskwid=maskwid*p_len) # masks fan in (Cat)
def connect_to_next(self, nxt, p_idx=0):
""" helper function to connect to the next stage data/valid/ready.
class MultiOutControlBase(Elaboratable):
""" Common functions for Pipeline API
"""
- def __init__(self, n_len=1, in_multi=None):
+ def __init__(self, n_len=1, in_multi=None, maskwid=0, routemask=False):
""" Multi-output Control class. Conforms to same API as ControlBase...
mostly. has additional indices to the multiple *output* stages
[MultiInControlBase has multiple *input* stages]
* add data_o members to NextControl
"""
+ if routemask:
+ nmaskwid = maskwid # straight route mask mode
+ else:
+ nmaskwid = maskwid * n_len # fan-out mode
+
# set up input and output IO ACK (prev/next ready/valid)
- self.p = PrevControl(in_multi)
+ self.p = PrevControl(in_multi, maskwid=nmaskwid)
n = []
for i in range(n_len):
- n.append(NextControl())
+ n.append(NextControl(maskwid=maskwid))
self.n = Array(n)
def connect_to_next(self, nxt, n_idx=0):
n.data_o : stage output data array. shaped according to ospec
"""
- def __init__(self, stage, n_len, n_mux):
- MultiOutControlBase.__init__(self, n_len=n_len)
+ def __init__(self, stage, n_len, n_mux, maskwid=0, routemask=False):
+ MultiOutControlBase.__init__(self, n_len=n_len, maskwid=maskwid,
+ routemask=routemask)
self.stage = stage
+ self.maskwid = maskwid
+ self.routemask = routemask
self.n_mux = n_mux
# set up the input and output data
m = MultiOutControlBase.elaborate(self, platform)
if hasattr(self.n_mux, "elaborate"): # TODO: identify submodule?
- m.submodules += self.n_mux
+ m.submodules.n_mux = self.n_mux
# need buffer register conforming to *input* spec
r_data = _spec(self.stage.ispec, 'r_data') # input type
self.stage.setup(m, r_data)
# multiplexer id taken from n_mux
- mid = self.n_mux.m_id
+ muxid = self.n_mux.m_id
print ("self.n_mux", self.n_mux)
print ("self.n_mux.m_id", self.n_mux.m_id)
p_valid_i = Signal(reset_less=True)
pv = Signal(reset_less=True)
m.d.comb += p_valid_i.eq(self.p.valid_i_test)
- m.d.comb += pv.eq(self.p.valid_i & self.p.ready_o)
+ m.d.comb += pv.eq(self.p.valid_i) #& self.n[muxid].ready_i)
# all outputs to next stages first initialised to zero (invalid)
# the only output "active" is then selected by the muxid
for i in range(len(self.n)):
m.d.comb += self.n[i].valid_o.eq(0)
- data_valid = self.n[mid].valid_o
- m.d.comb += self.p.ready_o.eq(~data_valid | self.n[mid].ready_i)
- m.d.comb += data_valid.eq(p_valid_i | \
- (~self.n[mid].ready_i & data_valid))
- with m.If(pv):
- m.d.comb += eq(r_data, self.p.data_i)
- m.d.comb += eq(self.n[mid].data_o, self.process(r_data))
-
+ #with m.If(pv):
+ m.d.comb += self.n[muxid].valid_o.eq(pv)
+ m.d.comb += self.p.ready_o.eq(self.n[muxid].ready_i)
+
+ # send data on
+ #with m.If(pv):
+ m.d.comb += eq(r_data, self.p.data_i)
+ m.d.comb += eq(self.n[muxid].data_o, self.process(r_data))
+
+ if self.maskwid:
+ if self.routemask: # straight "routing" mode - treat like data
+ m.d.comb += self.n[muxid].stop_o.eq(self.p.stop_i)
+ with m.If(pv):
+ m.d.comb += self.n[muxid].mask_o.eq(self.p.mask_i)
+ else:
+ ml = [] # accumulate output masks
+ ms = [] # accumulate output stops
+ # fan-out mode.
+ # conditionally fan-out mask bits, always fan-out stop bits
+ for i in range(len(self.n)):
+ ml.append(self.n[i].mask_o)
+ ms.append(self.n[i].stop_o)
+ m.d.comb += Cat(*ms).eq(self.p.stop_i)
+ with m.If(pv):
+ m.d.comb += Cat(*ml).eq(self.p.mask_i)
return m
SYNCHRONOUSLY.
"""
- def __init__(self, stage, p_len, p_mux):
- MultiInControlBase.__init__(self, p_len=p_len)
+ def __init__(self, stage, p_len, p_mux, maskwid=0, routemask=False):
+ MultiInControlBase.__init__(self, p_len=p_len, maskwid=maskwid,
+ routemask=routemask)
self.stage = stage
+ self.maskwid = maskwid
self.p_mux = p_mux
# set up the input and output data
def elaborate(self, platform):
m = MultiInControlBase.elaborate(self, platform)
- m.submodules += self.p_mux
+ m.submodules.p_mux = self.p_mux
# need an array of buffer registers conforming to *input* spec
r_data = []
p_valid_i.append(Signal(name="p_valid_i", reset_less=True))
n_ready_in.append(Signal(name="n_ready_in", reset_less=True))
if hasattr(self.stage, "setup"):
+ print ("setup", self, self.stage, r)
self.stage.setup(m, r)
if len(r_data) > 1:
r_data = Array(r_data)
nirn = Signal(reset_less=True)
m.d.comb += nirn.eq(~self.n.ready_i)
mid = self.p_mux.m_id
+ print ("CombMuxIn mid", self, self.stage, self.routemask, mid, p_len)
for i in range(p_len):
m.d.comb += data_valid[i].eq(0)
m.d.comb += n_ready_in[i].eq(1)
m.d.comb += p_valid_i[i].eq(0)
m.d.comb += self.p[i].ready_o.eq(0)
- m.d.comb += p_valid_i[mid].eq(self.p_mux.active)
+ p = self.p[mid]
+ maskedout = Signal(reset_less=True)
+ m.d.comb += maskedout.eq(p.mask_i & ~p.stop_i)
+ m.d.comb += p_valid_i[mid].eq(maskedout & self.p_mux.active)
m.d.comb += self.p[mid].ready_o.eq(~data_valid[mid] | self.n.ready_i)
m.d.comb += n_ready_in[mid].eq(nirn & data_valid[mid])
anyvalid = Signal(i, reset_less=True)
anyvalid = Cat(*av)
m.d.comb += self.n.valid_o.eq(anyvalid.bool())
m.d.comb += data_valid[mid].eq(p_valid_i[mid] | \
- (n_ready_in[mid] & data_valid[mid]))
-
- for i in range(p_len):
- vr = Signal(reset_less=True)
- m.d.comb += vr.eq(self.p[i].valid_i & self.p[i].ready_o)
- with m.If(vr):
- m.d.comb += eq(r_data[i], self.p[i].data_i)
+ (n_ready_in[mid] ))
+
+ if self.routemask:
+ # XXX hack - fixes loop
+ m.d.comb += eq(self.n.stop_o, self.p[0].stop_i)
+ for i in range(p_len):
+ p = self.p[i]
+ vr = Signal(reset_less=True)
+ maskedout = Signal(reset_less=True)
+ m.d.comb += maskedout.eq(p.mask_i & ~p.stop_i)
+ m.d.comb += vr.eq(maskedout.bool() & p.valid_i & p.ready_o)
+ #m.d.comb += vr.eq(p.valid_i & p.ready_o)
+ with m.If(vr):
+ m.d.comb += eq(self.n.mask_o, self.p[i].mask_i)
+ m.d.comb += eq(r_data[i], self.p[i].data_i)
+ else:
+ ml = [] # accumulate output masks
+ ms = [] # accumulate output stops
+ for i in range(p_len):
+ vr = Signal(reset_less=True)
+ p = self.p[i]
+ vr = Signal(reset_less=True)
+ maskedout = Signal(reset_less=True)
+ m.d.comb += maskedout.eq(p.mask_i & ~p.stop_i)
+ m.d.comb += vr.eq(maskedout.bool() & p.valid_i & p.ready_o)
+ with m.If(vr):
+ m.d.comb += eq(r_data[i], self.p[i].data_i)
+ if self.maskwid:
+ mlen = len(self.p[i].mask_i)
+ s = mlen*i
+ e = mlen*(i+1)
+ ml.append(Mux(vr, self.p[i].mask_i, Const(0, mlen)))
+ ms.append(self.p[i].stop_i)
+ if self.maskwid:
+ m.d.comb += self.n.mask_o.eq(Cat(*ml))
+ m.d.comb += self.n.stop_o.eq(Cat(*ms))
m.d.comb += eq(self.n.data_o, self.process(r_data[mid]))
class CombMuxOutPipe(CombMultiOutPipeline):
- def __init__(self, stage, n_len):
+ def __init__(self, stage, n_len, maskwid=0, muxidname=None,
+ routemask=False):
+ muxidname = muxidname or "muxid"
# HACK: stage is also the n-way multiplexer
- CombMultiOutPipeline.__init__(self, stage, n_len=n_len, n_mux=stage)
+ CombMultiOutPipeline.__init__(self, stage, n_len=n_len,
+ n_mux=stage, maskwid=maskwid,
+ routemask=routemask)
- # HACK: n-mux is also the stage... so set the muxid equal to input mid
- print ("combmuxout", self.p.data_i.mid)
- stage.m_id = self.p.data_i.mid
+ # HACK: n-mux is also the stage... so set the muxid equal to input muxid
+ muxid = getattr(self.p.data_i, muxidname)
+ print ("combmuxout", muxidname, muxid)
+ stage.m_id = muxid
in_ready = []
for i in range(self.num_rows):
p_valid_i = Signal(reset_less=True)
- m.d.comb += p_valid_i.eq(self.pipe.p[i].valid_i_test)
+ if self.pipe.maskwid and not self.pipe.routemask:
+ p = self.pipe.p[i]
+ maskedout = Signal(reset_less=True)
+ m.d.comb += maskedout.eq(p.mask_i & ~p.stop_i)
+ m.d.comb += p_valid_i.eq(maskedout.bool() & p.valid_i_test)
+ else:
+ m.d.comb += p_valid_i.eq(self.pipe.p[i].valid_i_test)
in_ready.append(p_valid_i)
m.d.comb += pe.i.eq(Cat(*in_ready)) # array of input "valids"
m.d.comb += self.active.eq(~pe.n) # encoder active (one input valid)
""" an example of how to use the combinatorial pipeline.
"""
- def __init__(self, stage, p_len=2):
+ def __init__(self, stage, p_len=2, maskwid=0, routemask=False):
p_mux = InputPriorityArbiter(self, p_len)
- CombMultiInPipeline.__init__(self, stage, p_len, p_mux)
+ CombMultiInPipeline.__init__(self, stage, p_len, p_mux,
+ maskwid=maskwid, routemask=routemask)
if __name__ == '__main__':