[libre-riscv-dev] pipeline stages controlling delays

Jacob Lifshay programmerjake at gmail.com
Sat Apr 6 00:16:38 BST 2019

On Fri, Apr 5, 2019, 01:02 Luke Kenneth Casson Leighton <lkcl at lkcl.net>

> On Fri, Apr 5, 2019 at 7:01 AM Jacob Lifshay <programmerjake at gmail.com>
> wrote:
> >
> > On Thu, Apr 4, 2019, 22:30 Luke Kenneth Casson Leighton <lkcl at lkcl.net>
> > wrote:
> >
> > > On Fri, Apr 5, 2019 at 6:06 AM Jacob Lifshay <programmerjake at gmail.com
> >
> > > wrote:
> > > > that's why I had put the control signals as members of Stage.
> > >
> > > ... which isn't needed in the majority of cases, hence why i separated
> > > them.
> >
> > which is why I made CombStage, to handle all the boilerplate code needed
> > for the most common cases.
> >
> > > plus, if they're part of the Stage, the temptation will be to
> > > override the *entirety* of the logic (or, worse *require* overriding
> > > all of the logic).
> > >
> > which is entirely feasible in the code I wrote because of separation of
> > concerns between RegStage and CombStage, so every Stage instance has a
> > uniform ready/valid interface, whereas BufferedPipeline and
> > UnbufferedPipeline make Stage have an interface that changes semantics
> > depending on how it's used.
>  that's a mistaken impression: in the pipeline API, a Stage is
> entirely independent of how it's used
ok. I was wrong.

> (or, it was: now it is responsible for dynamically indicating whether
> it is ready to receive data, and to dynamically indicate whether its
> output is ready.  however, again, that is related to the *data*, which
> has nothing to do at all with the *transfer or handling* of that
> data).
You would still need both ready and valid on both the input and output of a
FSM since a FSM could handle more than one data item at a time (eg. CORDIC
unit with 2-port lookup table can do 2 operations every 30 or so cycles for
f32)and the FSM needs the inputs that tell it if the input data is valid by
the next clock edge and if it should wait or can output data values right
away. Once you have both ready and valid on both input and output, then it
is simpler to just thread ready/valid through all the stages as I described.

> > >  what i believe all that is needed is just to create a surgical break
> > > in the p_o_ready and n_o_valid signals, and provide a couple of
> > > functions (in the stage instance) to connect the pairs of signals
> > > together.
> > >
> > Note that the BUF gates that yosys shows between wires should be
> optimized
> > out by the synthesis toolchain, so there is no penalty (except increasing
> > compile time by a little) to having long chains of signals that are wired
> > directly. That's part of why there is no problem routing ready/valid
> > through every stage instance.
>  the BUF gates get optimised out, however the actual chains of
> ready/valid signals do not, resulting in a gate cascade.  in
> particular, when a stage contains pause/stall logic, that gets
> inserted into the chain as well.
>  now, CombStage, _yes_, if several of those are chained together, as
> long as there is no pause/stall logic involved, the ready_out=ready_in
> and valid_out=valid_in will be optimised out...
>  ... except look at StageChain.  there *is* no ready/valid chain to
> create... because Stages *do not know about the signalling logic* and
> they do not have to.
>  except... *sigh*, now with the addition of ready/valid logic
> signalling by a Stage, that has to be thought through.  raising an
> exception (preventing StageChain from accepting a Stage with
> ready/valid logic) for now is the simplest option.

> > >  the Stage doesn't need to know, and definitely doesn't need access
> > > to, the p_i_valid or n_i_ready for example.  if those are part of the
> > > Stage, the Stage *will* have access to them, and may interfere
> > > unnecessarily with their operation.
> >
> >
> > > or, the end-user might *think*
> > > they have to interfere with their operation, because it's part of the
> > > "exposed API".
> > >
> > that's why the documentation should/will explicitly state that CombStage
> > handles prev/next ready/valid.
> > If a stage does something special with ready/valid, then it shouldn't be
> a
> > CombStage.
>  jacob, it's just not as flexible an API [and not actually *having*
> the stuff there is infinitely better than writing documentation (which
> people may or may not read) saying "don't use this"].

except that that stuff is necessary in some cases. What we could do is
create a StageWithReadyValid (needs a better name) and just use that as the
type that all stages are converted into by either being already
StageWithReadyValid or by being wrapped with CombStage, similar to how
integers are wrapped into valid nmigen Value instances.

(makes me wish we were using Rust:
CombStage would just be:
impl<I: SignalGroup, O: SignalGroup, F: Fn(I, &mut Module) -> O> Stage<I,
O> for F {...}

that way you could just use any function with the right prototype as a
Stage without needing to make a CombStage or anything.)

>  bear in mind: what you've written will need a complete redesign to
> allow the dozen different types of data format options currently
> supported by the pipeline API, and a yet further redesign to allow for
> use in a FSM, Global CE, travelling CE or STB/ACK handling
> arrangement.
I don't think supporting every possible kind of pipeline control should be
a goal. Ready/Valid is a generalization of travelling CE and probably some
others. Due to STB/ack (as described in your previous messages) not
supporting a data transfer every cycle, I would rule it out as a practical
pipeline control spec.

My current plan is to improve the code you wrote and use that as a base,
adding support for ready/valid signalling in each stage (or equivalent
using wrapper classes), RegStage and BreakReadyChainStage as separate Stage
classes (making UnbufferedPipeline and BufferedPipeline just be convenience
wrappers over StageChain, RegStage, and BreakReadyChainStage), and shifting
to using the Stage interface everywhere instead of having a separate
Pipeline interface.

>  by the time both of those near-total redesigns are done, the end
> result will be a direct functional equivalent of the *existing
> proposed pipeline API*
hence why I'll be building off of the existing code that you wrote.


> or did i misunderstand?
The FSMStage class would have yet-to-be-proposed improvements over
implementing Stage directly. We can figure those out when we actually write
a FSM.

> 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