[libre-riscv-dev] SV Prefix questions

Jacob Lifshay programmerjake at gmail.com
Tue Jun 25 21:48:37 BST 2019


On Tue, Jun 25, 2019, 08:29 Luke Kenneth Casson Leighton <lkcl at lkcl.net>
wrote:

> https://libre-riscv.org/simple_v_extension/sv_prefix_proposal/discussion/
>
> jacob: the compiler knows MAXVL at compile-time, however the engine does
> not, and must be told what it is.  then, loops like the DAXPY one from
> "SIMD Considered Harmful" will work (even on SV):
>
> # a0 is n, a1 is pointer to x[0], a2 is pointer to y[0], fa0 is a
>   0:  li t0, 2<<25
>   4:  vsetdcfg t0             # enable 2 64b Fl.Pt. registers
> loop:
>   8:  setvl  t0, a0           # vl = t0 = min(mvl, n)
>   c:  vld    v0, a1           # load vector x
>   10:  slli   t1, t0, 3        # t1 = vl * 8 (in bytes)
>   14:  vld    v1, a2           # load vector y
>   18:  add    a1, a1, t1       # increment pointer to x by vl*8
>   1c:  vfmadd v1, v0, fa0, v1  # v1 += v0 * fa0 (y = a * x + y)
>   20:  sub    a0, a0, t0       # n -= vl (t0)
>   24:  vst    v1, a2           # store Y
>   28:  add    a2, a2, t1       # increment pointer to y by vl*8
>   2c:  bnez   a0, loop         # repeat if n != 0
>   30:  ret                     # return
>
> in the above, let's say that MAXVL is 8 and a0 is 1,000.  SETVL goes "vl =
> t0 = min(8, 1000)" and sets both vl and t0 to 8 as a result.  clearly the
> next loop will do the same.
>
> only when a0 starts to drop *below* 8 will both vl and t0 be set to below 8
> (MVL).  in RVV, the implementor is allowed to start "throttling" by
> changing VL to 1/2 the value - this to prevent the "concertina" effect,
> apparently:
> https://en.wikipedia.org/wiki/Accordion_effect
>
> the thing is: i do not believe that the rules that you set would allow the
> same behaviour.  i did try creating something like it, a year ago:
> everything i could think of required either 2 to 3 additional instructions
> (inside the loop) because there was no way to get the same "vl = rd =
> min(rs, MVL)" behaviour as a single opcode, or it required a THIRD extra
> argument to SETVL - addition of the MAXVL value as a parameter (a constant
> or an immediate).
>
Just use setvli as the base instruction, the immediate has 11 bits --
plenty for MAXVL:
https://github.com/riscv/riscv-v-spec/blob/master/vcfg-format.adoc
if we don't want to conflict with the V extension, we could add a custom 32
or 48-bit instruction.

>
> that in turn would require the addition of an extra opcode, which is "off
> the table" as a hard requirement for SV.
>
it may be off the table for SVorig, but I think we should add it to
SVprefix -- it removes one CSR and reduces a common instruction sequence to
1 instruction rather than 2.
For SVorig, adding a MAXVL CSR seems like the only option.

>
> setting alternative rules, it's *essential* to come up with working demo
> pseudo-assembly.  after several weeks of thinking about this i gave up and
> decided to go with something that was very close to RVV.  this not just to
> save time and effort at the *design* phase, it's also to save on conceptual
> explanations and also on compiler development.
>
The semantics I had defined before you removed the setvl instruction from
SVprefix (putting a note that setvl was considered for removal would have
been better, since that way people could still read the definition) are the
same as the V extension when rs1 is not x0 except that I had the MAXVL <
rs1 < MAXVL * 2 case set VL to floor(rs1 / 2) instead of ceil(rs1 / 2), I
think ceil is a better option. MAXVL is the immediate operand. When rs1 is
x0, the instruction loads VL with MAXVL. The instruction I defined happened
to share the same mnemonic as the V extension's setvl, but is a separate
instruction.

Jacob


More information about the libre-riscv-dev mailing list