+# SPDX-License-Identifier: LGPL-3-or-later
""" Combinatorial Multi-input and Multi-output multiplexer blocks
conforming to Pipeline API
class MultiInControlBase(Elaboratable):
""" Common functions for Pipeline API
"""
+
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
* n: contains ready/valid to the next stage
User must also:
- * add data_i members to PrevControl and
- * add data_o member to NextControl
+ * add i_data members to PrevControl and
+ * add o_data member to NextControl
"""
self.routemask = routemask
# set up input and output IO ACK (prev/next ready/valid)
- print ("multi_in", self, maskwid, p_len, routemask)
+ print("multi_in", self, maskwid, p_len, routemask)
p = []
for i in range(p_len):
p.append(PrevControl(in_multi, maskwid=maskwid))
self.p = Array(p)
if routemask:
- nmaskwid = maskwid # straight route mask mode
+ nmaskwid = maskwid # straight route mask mode
else:
- nmaskwid = maskwid * p_len # fan-in mode
- self.n = NextControl(maskwid=nmaskwid) # masks fan in (Cat)
+ nmaskwid = maskwid * p_len # fan-in mode
+ self.n = NextControl(maskwid=nmaskwid) # masks fan in (Cat)
def connect_to_next(self, nxt, p_idx=0):
""" helper function to connect to the next stage data/valid/ready.
def set_input(self, i, idx=0):
""" helper function to set the input data
"""
- return eq(self.p[idx].data_i, i)
+ return eq(self.p[idx].i_data, i)
def elaborate(self, platform):
m = Module()
class MultiOutControlBase(Elaboratable):
""" Common functions for Pipeline API
"""
+
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
* n: contains ready/valid to the next stages PLURAL
User must also:
- * add data_i member to PrevControl and
- * add data_o members to NextControl
+ * add i_data member to PrevControl and
+ * add o_data members to NextControl
"""
if routemask:
- nmaskwid = maskwid # straight route mask mode
+ nmaskwid = maskwid # straight route mask mode
else:
- nmaskwid = maskwid * n_len # fan-out mode
+ nmaskwid = maskwid * n_len # fan-out mode
# set up input and output IO ACK (prev/next ready/valid)
self.p = PrevControl(in_multi, maskwid=nmaskwid)
def set_input(self, i):
""" helper function to set the input data
"""
- return eq(self.p.data_i, i)
+ return eq(self.p.i_data, i)
def __iter__(self):
yield from self.p
Attributes:
-----------
- p.data_i : stage input data (non-array). shaped according to ispec
- n.data_o : stage output data array. shaped according to ospec
+ p.i_data : stage input data (non-array). shaped according to ispec
+ n.o_data : stage output data array. shaped according to ospec
"""
def __init__(self, stage, n_len, n_mux, maskwid=0, routemask=False):
MultiOutControlBase.__init__(self, n_len=n_len, maskwid=maskwid,
- routemask=routemask)
+ routemask=routemask)
self.stage = stage
self.maskwid = maskwid
self.routemask = routemask
self.n_mux = n_mux
# set up the input and output data
- self.p.data_i = _spec(stage.ispec, 'data_i') # input type
+ self.p.i_data = _spec(stage.ispec, 'i_data') # input type
for i in range(n_len):
- name = 'data_o_%d' % i
- self.n[i].data_o = _spec(stage.ospec, name) # output type
+ name = 'o_data_%d' % i
+ self.n[i].o_data = _spec(stage.ospec, name) # output type
def process(self, i):
if hasattr(self.stage, "process"):
def elaborate(self, platform):
m = MultiOutControlBase.elaborate(self, platform)
- if hasattr(self.n_mux, "elaborate"): # TODO: identify submodule?
+ if hasattr(self.n_mux, "elaborate"): # TODO: identify submodule?
m.submodules.n_mux = self.n_mux
# need buffer register conforming to *input* spec
- r_data = _spec(self.stage.ispec, 'r_data') # input type
+ r_data = _spec(self.stage.ispec, 'r_data') # input type
if hasattr(self.stage, "setup"):
self.stage.setup(m, r_data)
# multiplexer id taken from n_mux
muxid = self.n_mux.m_id
- print ("self.n_mux", self.n_mux)
- print ("self.n_mux.m_id", self.n_mux.m_id)
+ print("self.n_mux", self.n_mux)
+ print("self.n_mux.m_id", self.n_mux.m_id)
self.n_mux.m_id.name = "m_id"
p_i_valid = Signal(reset_less=True)
pv = Signal(reset_less=True)
m.d.comb += p_i_valid.eq(self.p.i_valid_test)
- #m.d.comb += pv.eq(self.p.i_valid) #& self.n[muxid].i_ready)
+ # m.d.comb += pv.eq(self.p.i_valid) #& self.n[muxid].i_ready)
m.d.comb += pv.eq(self.p.i_valid & self.p.o_ready)
# all outputs to next stages first initialised to zero (invalid)
for i in range(len(self.n)):
m.d.comb += self.n[i].o_valid.eq(0)
if self.routemask:
- #with m.If(pv):
+ # with m.If(pv):
m.d.comb += self.n[muxid].o_valid.eq(pv)
m.d.comb += self.p.o_ready.eq(self.n[muxid].i_ready)
else:
data_valid = self.n[muxid].o_valid
- m.d.comb += self.p.o_ready.eq(~data_valid | self.n[muxid].i_ready)
- m.d.comb += data_valid.eq(p_i_valid | \
- (~self.n[muxid].i_ready & data_valid))
-
+ m.d.comb += self.p.o_ready.eq(self.n[muxid].i_ready)
+ m.d.comb += data_valid.eq(p_i_valid |
+ (~self.n[muxid].i_ready & data_valid))
# 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))
+ # with m.If(pv):
+ m.d.comb += eq(r_data, self.p.i_data)
+ #m.d.comb += eq(self.n[muxid].o_data, self.process(r_data))
+ for i in range(len(self.n)):
+ with m.If(muxid == i):
+ m.d.comb += eq(self.n[i].o_data, self.process(r_data))
if self.maskwid:
- if self.routemask: # straight "routing" mode - treat like data
+ 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
+ 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)):
Attributes:
-----------
- p.data_i : StageInput, shaped according to ispec
+ p.i_data : StageInput, shaped according to ispec
The pipeline input
- p.data_o : StageOutput, shaped according to ospec
+ p.o_data : StageOutput, shaped according to ospec
The pipeline output
r_data : input_shape according to ispec
A temporary (buffered) copy of a prior (valid) input.
def __init__(self, stage, p_len, p_mux, maskwid=0, routemask=False):
MultiInControlBase.__init__(self, p_len=p_len, maskwid=maskwid,
- routemask=routemask)
+ routemask=routemask)
self.stage = stage
self.maskwid = maskwid
self.p_mux = p_mux
# set up the input and output data
for i in range(p_len):
- name = 'data_i_%d' % i
- self.p[i].data_i = _spec(stage.ispec, name) # input type
- self.n.data_o = _spec(stage.ospec, 'data_o')
+ name = 'i_data_%d' % i
+ self.p[i].i_data = _spec(stage.ispec, name) # input type
+ self.n.o_data = _spec(stage.ospec, 'o_data')
def process(self, i):
if hasattr(self.stage, "process"):
p_len = len(self.p)
for i in range(p_len):
name = 'r_%d' % i
- r = _spec(self.stage.ispec, name) # input type
+ r = _spec(self.stage.ispec, name) # input type
r_data.append(r)
data_valid.append(Signal(name="data_valid", reset_less=True))
p_i_valid.append(Signal(name="p_i_valid", reset_less=True))
n_i_readyn.append(Signal(name="n_i_readyn", reset_less=True))
if hasattr(self.stage, "setup"):
- print ("setup", self, self.stage, r)
+ print("setup", self, self.stage, r)
self.stage.setup(m, r)
- if len(r_data) > 1:
- r_data = Array(r_data)
+ if True: # len(r_data) > 1: # hmm always create an Array even of len 1
p_i_valid = Array(p_i_valid)
n_i_readyn = Array(n_i_readyn)
data_valid = Array(data_valid)
nirn = Signal(reset_less=True)
m.d.comb += nirn.eq(~self.n.i_ready)
mid = self.p_mux.m_id
- print ("CombMuxIn mid", self, self.stage, self.routemask, mid, p_len)
+ 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_i_readyn[i].eq(1)
m.d.comb += maskedout.eq(p.mask_i & ~p.stop_i)
else:
m.d.comb += maskedout.eq(1)
- m.d.comb += p_i_valid[mid].eq(maskedout & self.p_mux.active)
+ m.d.comb += p_i_valid[mid].eq(maskedout & self.p_mux.active &
+ self.p[mid].i_valid)
m.d.comb += self.p[mid].o_ready.eq(~data_valid[mid] | self.n.i_ready)
m.d.comb += n_i_readyn[mid].eq(nirn & data_valid[mid])
anyvalid = Signal(i, reset_less=True)
av.append(data_valid[i])
anyvalid = Cat(*av)
m.d.comb += self.n.o_valid.eq(anyvalid.bool())
- m.d.comb += data_valid[mid].eq(p_i_valid[mid] | \
- (n_i_readyn[mid] ))
+ m.d.comb += data_valid[mid].eq(p_i_valid[mid] |
+ (n_i_readyn[mid]))
if self.routemask:
# XXX hack - fixes loop
#m.d.comb += vr.eq(p.i_valid & p.o_ready)
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)
+ m.d.comb += eq(r_data[i], self.process(self.p[i].i_data))
+ with m.If(mid == i):
+ m.d.comb += eq(self.n.o_data, r_data[i])
else:
- ml = [] # accumulate output masks
- ms = [] # accumulate output stops
+ ml = [] # accumulate output masks
+ ms = [] # accumulate output stops
for i in range(p_len):
vr = Signal(reset_less=True)
p = self.p[i]
m.d.comb += maskedout.eq(1)
m.d.comb += vr.eq(maskedout.bool() & p.i_valid & p.o_ready)
with m.If(vr):
- m.d.comb += eq(r_data[i], self.p[i].data_i)
+ m.d.comb += eq(r_data[i], self.process(self.p[i].i_data))
+ with m.If(mid == i):
+ m.d.comb += eq(self.n.o_data, r_data[i])
if self.maskwid:
mlen = len(self.p[i].mask_i)
s = mlen*i
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]))
+ #print ("o_data", self.n.o_data, "r_data[mid]", mid, r_data[mid])
+ #m.d.comb += eq(self.n.o_data, r_data[mid])
return m
Attributes:
-----------
- p.data_i : StageInput, shaped according to ispec
+ p.i_data : StageInput, shaped according to ispec
The pipeline input
- p.data_o : StageOutput, shaped according to ospec
+ p.o_data : StageOutput, shaped according to ospec
The pipeline output
r_data : input_shape according to ispec
A temporary (buffered) copy of a prior (valid) input.
def __init__(self, stage, p_len, p_mux, maskwid=0, routemask=False):
MultiInControlBase.__init__(self, p_len=p_len, maskwid=maskwid,
- routemask=routemask)
+ routemask=routemask)
self.stage = stage
self.maskwid = maskwid
self.p_mux = p_mux
# set up the input and output data
for i in range(p_len):
- name = 'data_i_%d' % i
- self.p[i].data_i = _spec(stage.ispec, name) # input type
- self.n.data_o = _spec(stage.ospec, 'data_o')
+ name = 'i_data_%d' % i
+ self.p[i].i_data = _spec(stage.ispec, name) # input type
+ self.n.o_data = _spec(stage.ospec, 'o_data')
def process(self, i):
if hasattr(self.stage, "process"):
p_len = len(self.p)
for i in range(p_len):
name = 'r_%d' % i
- r = _spec(self.stage.ispec, name) # input type
+ r = _spec(self.stage.ispec, name) # input type
r_data.append(r)
r_busy.append(Signal(name="r_busy%d" % i, reset_less=True))
p_i_valid.append(Signal(name="p_i_valid%d" % i, reset_less=True))
if hasattr(self.stage, "setup"):
- print ("setup", self, self.stage, r)
+ 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.i_ready)
mid = self.p_mux.m_id
- print ("CombMuxIn mid", self, self.stage, self.routemask, mid, p_len)
+ print("CombMuxIn mid", self, self.stage, self.routemask, mid, p_len)
for i in range(p_len):
m.d.comb += r_busy[i].eq(0)
m.d.comb += n_i_readyn[i].eq(1)
av.append(data_valid[i])
anyvalid = Cat(*av)
m.d.comb += self.n.o_valid.eq(anyvalid.bool())
- m.d.comb += data_valid[mid].eq(p_i_valid[mid] | \
- (n_i_readyn[mid] ))
+ m.d.comb += data_valid[mid].eq(p_i_valid[mid] |
+ (n_i_readyn[mid]))
if self.routemask:
# XXX hack - fixes loop
#m.d.comb += vr.eq(p.i_valid & p.o_ready)
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)
+ m.d.comb += eq(r_data[i], self.p[i].i_data)
else:
- ml = [] # accumulate output masks
- ms = [] # accumulate output stops
+ ml = [] # accumulate output masks
+ ms = [] # accumulate output stops
for i in range(p_len):
vr = Signal(reset_less=True)
p = self.p[i]
m.d.comb += maskedout.eq(1)
m.d.comb += vr.eq(maskedout.bool() & p.i_valid & p.o_ready)
with m.If(vr):
- m.d.comb += eq(r_data[i], self.p[i].data_i)
+ m.d.comb += eq(r_data[i], self.p[i].i_data)
if self.maskwid:
mlen = len(self.p[i].mask_i)
s = mlen*i
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]))
+ m.d.comb += eq(self.n.o_data, self.process(r_data[mid]))
return m
class CombMuxOutPipe(CombMultiOutPipeline):
def __init__(self, stage, n_len, maskwid=0, muxidname=None,
- routemask=False):
+ 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, maskwid=maskwid,
- routemask=routemask)
+ n_mux=stage, maskwid=maskwid,
+ routemask=routemask)
# 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)
+ muxid = getattr(self.p.i_data, muxidname)
+ print("combmuxout", muxidname, muxid)
stage.m_id = muxid
-
class InputPriorityArbiter(Elaboratable):
""" arbitration module for Input-Mux pipe, baed on PriorityEncoder
"""
+
def __init__(self, pipe, num_rows):
self.pipe = pipe
self.num_rows = num_rows
self.mmax = int(log(self.num_rows) / log(2))
- self.m_id = Signal(self.mmax, reset_less=True) # multiplex id
+ self.m_id = Signal(self.mmax, reset_less=True) # multiplex id
self.active = Signal(reset_less=True)
def elaborate(self, platform):
m = Module()
assert len(self.pipe.p) == self.num_rows, \
- "must declare input to be same size"
+ "must declare input to be same size"
pe = PriorityEncoder(self.num_rows)
m.submodules.selector = pe
else:
m.d.comb += p_i_valid.eq(self.pipe.p[i].i_valid_test)
in_ready.append(p_i_valid)
- m.d.comb += pe.i.eq(Cat(*in_ready)) # array of input "valids"
+ 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)
m.d.comb += self.m_id.eq(pe.o) # output one active input
return [self.m_id, self.active]
-
class PriorityCombMuxInPipe(CombMultiInPipeline):
""" an example of how to use the combinatorial pipeline.
"""