[libre-riscv-dev] buffered pipeline
Luke Kenneth Casson Leighton
lkcl at lkcl.net
Wed Mar 27 11:55:02 GMT 2019
this is what RegStage can be replaced with:
class PassThroughStage(StageCls):
def __init__(self, iospec): self.iospecfn = iospecfn
def ispec(self): return self.iospecfn()
def ospec(self): return self.iospecfn()
def process(self, i): return i
class RegisterPipeline(UnbufferedPipeline):
def __init__(self, iospecfn):
UnbufferedPipeline.__init__(self, PassThroughStage(iospecfn))
initially i wrote this (based directly on RegStage - one-for-one
correspondance):
def elaborate(self, platform):
m = Module()
# some temporaries
p_i_valid = Signal(reset_less=True)
pv = Signal(reset_less=True)
m.d.comb += [p_i_valid.eq(self.p.i_valid_logic()),
pv.eq(p_i_valid & self.p.o_ready)]
# set prev/next ready/valid
m.d.comb += self.p.o_ready.eq(~self.n.o_valid | self.n.i_ready)
m.d.sync += self.n.o_valid.eq(p_i_valid
| (~self.n.i_ready & self.n.o_valid))
# output data if input is valid and output is ready
with m.If(pv):
m.d.sync += eq(self.n.o_data, self.p.i_data)
return m
however i realised that, actually, that's near-identical to
UnbufferedPipeline, except that the sync of the data is put into a
temporary named "register" first, and that the call to stage.process()
is missed out.
that allowed me to think, "hmmm, if you have a stage which just passes
through its data, and has the exact same input-spec as output-spec,
that's the job done".
the temporary named pv *is* data_valid (aka inverted buffer_full).
so there's direct one-to-one equivalence between the code that you've
written, and the preliminary Stage/Pipeline API, with the exception
that StageChain, BufferedPipeline and the ability to support an
arbitrary recursive mixture of objects, Records and Signals are
missing.
l.
More information about the libre-riscv-dev
mailing list