[libre-riscv-dev] buffered pipeline

Luke Kenneth Casson Leighton lkcl at lkcl.net
Mon Mar 18 12:18:28 GMT 2019

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.


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]


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.

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

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

it's aalllmost at the point where i could consider using it in


More information about the libre-riscv-dev mailing list