def __init__(self, in_shape, out_shape, processfn, setupfn=None):
self.in_shape = in_shape
self.out_shape = out_shape
self.__process = processfn
self.__setup = setupfn
def __init__(self, in_shape, out_shape, processfn, setupfn=None):
self.in_shape = in_shape
self.out_shape = out_shape
self.__process = processfn
self.__setup = setupfn
def ispec(self): return Record(self.in_shape)
def ospec(self): return Record(self.out_shape)
def process(seif, i): return self.__process(i)
def ispec(self): return Record(self.in_shape)
def ospec(self): return Record(self.out_shape)
def process(seif, i): return self.__process(i)
(many APIs would potentially use a static "wrap" method in e.g.
StageCls to achieve a similar effect)
"""
(many APIs would potentially use a static "wrap" method in e.g.
StageCls to achieve a similar effect)
"""
def __init__(self, iospecfn): self.iospecfn = iospecfn
def ispec(self): return self.iospecfn()
def ospec(self): return self.iospecfn()
def __init__(self, iospecfn): self.iospecfn = iospecfn
def ispec(self): return self.iospecfn()
def ospec(self): return self.iospecfn()
*BYPASSES* a ControlBase instance ready/valid signalling, which
clearly should not be done without a really, really good reason.
"""
*BYPASSES* a ControlBase instance ready/valid signalling, which
clearly should not be done without a really, really good reason.
"""
def __init__(self, stage=None, in_multi=None, stage_ctl=False, maskwid=0):
""" Base class containing ready/valid/data to previous and next stages
def __init__(self, stage=None, in_multi=None, stage_ctl=False, maskwid=0):
""" Base class containing ready/valid/data to previous and next stages
- print ("ControlBase", self, stage, in_multi, stage_ctl)
+ print("ControlBase", self, stage, in_multi, stage_ctl)
StageHelper.__init__(self, stage)
# set up input and output IO ACK (prev/next ready/valid)
StageHelper.__init__(self, stage)
# set up input and output IO ACK (prev/next ready/valid)
"""
assert len(pipechain) > 0, "pipechain must be non-zero length"
assert self.stage is None, "do not use connect with a stage"
"""
assert len(pipechain) > 0, "pipechain must be non-zero length"
assert self.stage is None, "do not use connect with a stage"
# connect inter-chain
for i in range(len(pipechain)-1):
pipe1 = pipechain[i] # earlier
pipe2 = pipechain[i+1] # later (by 1)
# connect inter-chain
for i in range(len(pipechain)-1):
pipe1 = pipechain[i] # earlier
pipe2 = pipechain[i+1] # later (by 1)
# connect front and back of chain to ourselves
front = pipechain[0] # first in chain
end = pipechain[-1] # last in chain
# connect front and back of chain to ourselves
front = pipechain[0] # first in chain
end = pipechain[-1] # last in chain
- self.set_specs(front, end) # sets up ispec/ospec functions
- self._new_data("chain") # NOTE: REPLACES existing data
+ self.set_specs(front, end) # sets up ispec/ospec functions
+ self._new_data("chain") # NOTE: REPLACES existing data
por_pivn = Signal(reset_less=True)
npnn = Signal(reset_less=True)
self.m.d.comb += [p_i_valid.eq(self.p.i_valid_test),
por_pivn = Signal(reset_less=True)
npnn = Signal(reset_less=True)
self.m.d.comb += [p_i_valid.eq(self.p.i_valid_test),
- o_n_validn.eq(~self.n.o_valid),
- n_i_ready.eq(self.n.i_ready_test),
- nir_por.eq(n_i_ready & self.p._o_ready),
- nir_por_n.eq(n_i_ready & ~self.p._o_ready),
- nir_novn.eq(n_i_ready | o_n_validn),
- nirn_novn.eq(~n_i_ready & o_n_validn),
- npnn.eq(nir_por | nirn_novn),
- por_pivn.eq(self.p._o_ready & ~p_i_valid)
- ]
+ o_n_validn.eq(~self.n.o_valid),
+ n_i_ready.eq(self.n.i_ready_test),
+ nir_por.eq(n_i_ready & self.p._o_ready),
+ nir_por_n.eq(n_i_ready & ~self.p._o_ready),
+ nir_novn.eq(n_i_ready | o_n_validn),
+ nirn_novn.eq(~n_i_ready & o_n_validn),
+ npnn.eq(nir_por | nirn_novn),
+ por_pivn.eq(self.p._o_ready & ~p_i_valid)
+ ]
# store result of processing in combinatorial temporary
self.m.d.comb += nmoperator.eq(result, self.data_r)
# if not in stall condition, update the temporary register
# store result of processing in combinatorial temporary
self.m.d.comb += nmoperator.eq(result, self.data_r)
# if not in stall condition, update the temporary register
- with self.m.If(self.p.o_ready): # not stalled
- self.m.d.sync += nmoperator.eq(r_data, result) # update buffer
+ with self.m.If(self.p.o_ready): # not stalled
+ self.m.d.sync += nmoperator.eq(r_data, result) # update buffer
- o_data = self._postprocess(result) # XXX TBD, does nothing right now
- self.m.d.sync += [self.n.o_valid.eq(p_i_valid), # valid if p_valid
- nmoperator.eq(self.n.o_data, o_data), # update out
- ]
+ # XXX TBD, does nothing right now
+ o_data = self._postprocess(result)
+ self.m.d.sync += [self.n.o_valid.eq(p_i_valid), # valid if p_valid
+ # update out
+ nmoperator.eq(self.n.o_data, o_data),
+ ]
def __init__(self, stage, maskwid, in_multi=None, stage_ctl=False):
ControlBase.__init__(self, stage, in_multi, stage_ctl, maskwid)
def __init__(self, stage, maskwid, in_multi=None, stage_ctl=False):
ControlBase.__init__(self, stage, in_multi, stage_ctl, maskwid)
m.d.sync += self.n.o_valid.eq(p_i_valid)
m.d.sync += self.n.mask_o.eq(Mux(p_i_valid, maskedout, 0))
with m.If(p_i_valid):
m.d.sync += self.n.o_valid.eq(p_i_valid)
m.d.sync += self.n.mask_o.eq(Mux(p_i_valid, maskedout, 0))
with m.If(p_i_valid):
- o_data = self._postprocess(result) # XXX TBD, does nothing right now
- m.d.sync += nmoperator.eq(self.n.o_data, o_data) # update output
+ # XXX TBD, does nothing right now
+ o_data = self._postprocess(result)
+ m.d.sync += nmoperator.eq(self.n.o_data, o_data) # update output
def __init__(self, stage, maskwid, in_multi=None, stage_ctl=False,
def __init__(self, stage, maskwid, in_multi=None, stage_ctl=False,
ControlBase.__init__(self, stage, in_multi, stage_ctl, maskwid)
self.dynamic = dynamic
if dynamic:
ControlBase.__init__(self, stage, in_multi, stage_ctl, maskwid)
self.dynamic = dynamic
if dynamic:
m.d.comb += [p_i_valid.eq(self.p.i_valid_test & maskedout.bool()),
n_i_ready.eq(self.n.i_ready_test),
p_i_valid_p_o_ready.eq(p_i_valid & self.p.o_ready),
m.d.comb += [p_i_valid.eq(self.p.i_valid_test & maskedout.bool()),
n_i_ready.eq(self.n.i_ready_test),
p_i_valid_p_o_ready.eq(p_i_valid & self.p.o_ready),
# if idmask nonzero, mask gets passed on (and register set).
# register is left as-is if idmask is zero, but out-mask is set to
# if idmask nonzero, mask gets passed on (and register set).
# register is left as-is if idmask is zero, but out-mask is set to
m.d.sync += r_busy.eq(1) # output valid
# previous invalid or not ready, however next is accepting
with m.Elif(n_i_ready):
m.d.sync += r_busy.eq(1) # output valid
# previous invalid or not ready, however next is accepting
with m.Elif(n_i_ready):
# output set combinatorially from latch
m.d.comb += nmoperator.eq(self.n.o_data, r_latch)
# output set combinatorially from latch
m.d.comb += nmoperator.eq(self.n.o_data, r_latch)
m.d.comb += [p_i_valid.eq(self.p.i_valid_test),
n_i_ready.eq(self.n.i_ready_test),
p_i_valid_p_o_ready.eq(p_i_valid & self.p.o_ready),
m.d.comb += [p_i_valid.eq(self.p.i_valid_test),
n_i_ready.eq(self.n.i_ready_test),
p_i_valid_p_o_ready.eq(p_i_valid & self.p.o_ready),
# store result of processing in combinatorial temporary
m.d.comb += nmoperator.eq(result, self.data_r)
# previous valid and ready
with m.If(p_i_valid_p_o_ready):
# store result of processing in combinatorial temporary
m.d.comb += nmoperator.eq(result, self.data_r)
# previous valid and ready
with m.If(p_i_valid_p_o_ready):
m.d.sync += [nmoperator.eq(self.n.o_data, o_data)]
# TODO: could still send data here (if there was any)
m.d.sync += [nmoperator.eq(self.n.o_data, o_data)]
# TODO: could still send data here (if there was any)
- #m.d.sync += self.n.o_valid.eq(0) # ...so set output invalid
- m.d.sync += r_busy.eq(0) # ...so set output invalid
+ # m.d.sync += self.n.o_valid.eq(0) # ...so set output invalid
+ m.d.sync += r_busy.eq(0) # ...so set output invalid
m.d.comb += self.n.o_valid.eq(r_busy)
# if next is ready, so is previous
m.d.comb += self.n.o_valid.eq(r_busy)
# if next is ready, so is previous
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
- data_valid = Signal() # is data valid or not
- r_data = _spec(self.stage.ospec, "r_tmp") # output type
+ data_valid = Signal() # is data valid or not
+ r_data = _spec(self.stage.ospec, "r_tmp") # output type
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
- buf_full = Signal() # is data valid or not
- buf = _spec(self.stage.ospec, "r_tmp") # output type
+ buf_full = Signal() # is data valid or not
+ buf = _spec(self.stage.ospec, "r_tmp") # output type
m.d.sync += buf_full.eq(~self.n.i_ready_test & self.n.o_valid)
o_data = Mux(buf_full, buf, self.data_r)
m.d.sync += buf_full.eq(~self.n.i_ready_test & self.n.o_valid)
o_data = Mux(buf_full, buf, self.data_r)
m.d.comb += nmoperator.eq(self.n.o_data, o_data)
m.d.sync += nmoperator.eq(buf, self.n.o_data)
m.d.comb += nmoperator.eq(self.n.o_data, o_data)
m.d.sync += nmoperator.eq(buf, self.n.o_data)
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
- m.d.comb += self.p.o_ready.eq(~self.n.o_valid | self.n.i_ready_test)
- m.d.sync += self.n.o_valid.eq(p_i_valid | ~self.p.o_ready)
+ m.d.comb += self.p.o_ready.eq(~self.n.o_valid | self.n.i_ready_test)
+ m.d.sync += self.n.o_valid.eq(p_i_valid | ~self.p.o_ready)
odata = Mux(pvr, self.data_r, r_data)
m.d.sync += nmoperator.eq(r_data, odata)
odata = Mux(pvr, self.data_r, r_data)
m.d.sync += nmoperator.eq(r_data, odata)
def __init__(self, iospecfn):
UnbufferedPipeline.__init__(self, PassThroughStage(iospecfn))
def __init__(self, iospecfn):
UnbufferedPipeline.__init__(self, PassThroughStage(iospecfn))
def __init__(self, depth, stage, in_multi=None, stage_ctl=False,
def __init__(self, depth, stage, in_multi=None, stage_ctl=False,
m.d.comb += nmoperator.eq(result, self.process(i_data))
return nmoperator.cat(result)
m.d.comb += nmoperator.eq(result, self.process(i_data))
return nmoperator.cat(result)
m.submodules.fp = fp = PrevControl()
fp.i_valid, fp._o_ready, fp.i_data = fifo.w_en, fifo.w_rdy, fifo.w_data
m.d.comb += fp._connect_in(self.p, fn=processfn)
# next: make the FIFO (Queue object) "look" like a NextControl...
m.submodules.fn = fn = NextControl()
m.submodules.fp = fp = PrevControl()
fp.i_valid, fp._o_ready, fp.i_data = fifo.w_en, fifo.w_rdy, fifo.w_data
m.d.comb += fp._connect_in(self.p, fn=processfn)
# next: make the FIFO (Queue object) "look" like a NextControl...
m.submodules.fn = fn = NextControl()
- fn.o_valid, fn.i_ready, fn.o_data = fifo.r_rdy, fifo.r_en, fifo.r_data
+ fn.o_valid, fn.i_ready, fn.o_data = fifo.r_rdy, fifo.r_en, fifo.r_data
connections = fn._connect_out(self.n, fn=nmoperator.cat)
valid_eq, ready_eq, o_data = connections
# ok ok so we can't just do the ready/valid eqs straight:
# first 2 from connections are the ready/valid, 3rd is data.
if self.fwft:
connections = fn._connect_out(self.n, fn=nmoperator.cat)
valid_eq, ready_eq, o_data = connections
# ok ok so we can't just do the ready/valid eqs straight:
# first 2 from connections are the ready/valid, 3rd is data.
if self.fwft:
- m.d.sync += [valid_eq, ready_eq] # non-fwft mode needs sync
- o_data = self._postprocess(o_data) # XXX TBD, does nothing right now
+ m.d.sync += [valid_eq, ready_eq] # non-fwft mode needs sync
+ o_data = self._postprocess(o_data) # XXX TBD, does nothing right now
class UnbufferedPipeline(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 1, stage, in_multi, stage_ctl,
class UnbufferedPipeline(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 1, stage, in_multi, stage_ctl,
class PassThroughHandshake(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 1, stage, in_multi, stage_ctl,
class PassThroughHandshake(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 1, stage, in_multi, stage_ctl,
class BufferedHandshake(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 2, stage, in_multi, stage_ctl,
class BufferedHandshake(FIFOControl):
def __init__(self, stage, in_multi=None, stage_ctl=False):
FIFOControl.__init__(self, 2, stage, in_multi, stage_ctl,