[libre-riscv-dev] buffered pipeline

Jacob Lifshay programmerjake at gmail.com
Mon Mar 18 16:10:38 GMT 2019

On Mon, Mar 18, 2019, 05:19 Luke Kenneth Casson Leighton <lkcl at lkcl.net>

> ok so i implemented the ideas i had for a pipeline stage API, to
> create an input "spec" function and an output "spec" function that
> return a Signal, a list/tuple of signals, or an object that has an
> "eq" function.
> https://git.libre-riscv.org/?p=ieee754fpu.git;a=blob;f=src/add/example_buf_pipe.py;hb=HEAD
> i also separated Stage from the actual Pipeline class, and it turns
> out that the stage can be a static class.  an add pipeline can be as
> simple as this:
> class ExampleAddStage:
>     def ispec(self): return (Signal(16), Signal(16))
>     def ospec(self): return Signal(16)
>     def process(self, i): return i[0] + i[1]
> or:
> class ExampleAddStage:
>     def ispec(): return (Signal(16), Signal(16))
>     def ospec(): return Signal(16)
>     def process(i): return i[0] + i[1]
> and need not really know anything about how the actual pipeline itself
> works.  doesn't need to set up any input variables, doesn't need to
> set up any output variables, nor any intermediary registers, nor this,
> nor that, nor blah blah.
> *all* it needs to do is specify the format of the input, specify the
> format of the output, and process incoming data in the specified
> "input format" and return data in the "output" format.
> so it's a little different from the pipeline example you created,
> jacob, in that there's no need for explicit mention of or involvement
> of combinatorial logic, no module needs to be set up and so on.
I think that's fine, but we still need a way to have intermediate Signals
in our pipeline stage, since that's the only way to convert the
intermediate value to signed. See the implementation of alu.py sra/srl and
slt/sltu for examples where that is necessary.

> it's taking advantage of the features of python, by passing around
> (and returning) nmigen HDL fragments, rather than actually having the
> python code *do* the nmigen m.d.comb += in an explicit fashion: that's
> handled by the *base* class, such that the writer of the Stage doesn't
> have to.
> so in test_pipeline.py:
>             def elaborate(self, platform: Any) -> Module:
>                 m = super().elaborate(platform)
>                 m.d.comb += self.comb_output.eq(self.comb_input + 1)
>                 return m
> that could be removed and replaced with this in the base class:
>             def elaborate_more(self, platform: Any) -> Module:
>                 m = self.elaborate(platform)
>                 m.d.comb +=
> self.comb_output.eq(self.process(self.comb_input)
>                 return m
actually, it needs to be named elaborate since that's the name of the
function called by nmigen when you pass this class as an object to nmigen.
m.submodules.add = AddStage() # nmigen calls elaborate for us

> or actually just combine the m.d.comb line directly into
> SimpleStage.elaborate() and then create a process function like this:
>             def elaborate(self, i):
>                 return i+1
assuming you meant def process()

> it's aalllmost at the point where i could consider using it in
> nmigen_add_experiment.py
> l.
> _______________________________________________
> libre-riscv-dev mailing list
> libre-riscv-dev at lists.libre-riscv.org
> http://lists.libre-riscv.org/mailman/listinfo/libre-riscv-dev

More information about the libre-riscv-dev mailing list