[libre-riscv-dev] buffered pipeline

Luke Kenneth Casson Leighton lkcl at lkcl.net
Thu Mar 14 13:51:30 GMT 2019


yay, that works! split out send from receive, on their own separate clocked
co-routines.  Simulation() takes care of multiplexing / synchronising them,
based on the clock "yield" timing.

without such an approach it's almost impossible to manually interleave the
send/receives (or other interactions, of which there could be potentially
dozens) in a way that can be interpreted and understood by looking at the

so, for example, jacob, i notice that the unit test that you wrote, there
are two yield statements: one on "set data" and the other on "clear data

                    # set data
                    yield test_stage.input.data.eq(0xAAAA)
                    yield test_stage.input.sending.eq(1)
                    yield test_stage.output.accepting.eq(1)
                    yield delay_into_cycle
                    # clear data_valid
                    yield test_stage.input.sending.eq(0)
                    yield test_stage.output.accepting.eq(1)
                    yield delay_into_cycle

what that means is: the data is only sent every *two* cycles, which means
that the pipeline is only 50% utilised... in turn, that means that
potential conditions where it could fail (lose data, or data corruption)
are not being tested.

a split sender co-routine as separate and distinct from the receiver
co-routine would allow the sending to potentially occur on every clock.

i like the idea of comprehensive coverage of data valid, sending and
accepting: my only concern is that they're regularly scheduled.  as in: the
possible permutations of the *order* in which the combinations of
data-valid / sending / accepting can occur (be set and unset) has not been
covered, leaving the possibility that some combinations might fail as being

that was why i used a random setting of the accept and send conditions, but
also varied the distribution of time that each could spend set / unset (see
send_range and stall_range).

what that does is: sets up between 1 and 10 cycles where (potentially) the
sender is mostly idle and the receiver is mostly accepting, and then on the
next 1-10 cycle group, it could be the other way round.  then, also,
sometimes, there's no stalling and the receiver is never busy.

repeat for 10,000 values and we have a high degree of confidence that the
buffered pipeline (and a 2-stage chain) works as advertised.


More information about the libre-riscv-dev mailing list