* <https://bugs.libre-soc.org/show_bug.cgi?id=535>
* <https://bugs.libre-soc.org/show_bug.cgi?id=587>
* <https://bugs.libre-soc.org/show_bug.cgi?id=568> TODO
+* <https://bugs.libre-soc.org/show_bug.cgi?id=862> VF Predication
* <https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vsetvlivsetvl-instructions>
-* old page [[simple_v_extension/specification/sv.setvl]]
* [[sv/svstep]]
+* pseudocode [[openpower/isa/simplev]]
Use of setvl results in changes to the MVL, VL and STATE SPRs. see [[sv/sprs]]♧
Form: SVL-Form (see [[isatables/fields.text]])
-| 0.5|6.10|11.15|16..21| 22...25 | 26.30 |31| name |
+| 0.5|6.10|11.15|16..22| 23...25 | 26.30 |31| name |
| -- | -- | --- | ---- |----------- | ----- |--| ------- |
-|OPCD| RT | RA | SVi |cv ms vs vf | 11110 |Rc| setvl |
+|OPCD| RT | RA | SVi | ms vs vf | 11011 |Rc| setvl |
Instruction format:
Note that the immediate (`SVi`) spans 7 bits (16 to 22)
-* `cv` - bit 22 - reads CTR instead of RA
* `ms` - bit 23 - allows for setting of MVL.
* `vs` - bit 24 - allows for setting of VL.
* `vf` - bit 25 - sets "Vertical First Mode".
Vertical First is effectively like an implicit single bit predicate
applied to every SVP64 instruction. **ONLY** one element in each
SVP64 Vector instruction is executed; srcstep and dststep do **not**
-increment, and the Program Counter progresses **immediately* to
+increment, and the Program Counter progresses **immediately** to
the next instruction just as it would for any standard scalar v3.0B
instruction.
Nested looping with different schedules is perfectly possible, as is
calling of functions, however SVSTATE (and any associated SVSTATE) should be stored on the stack.*
+**SUBVL**
+
+Sub-vector elements are not be considered "Vertical". The vec2/3/4
+is to be considered as if the "single element". Caveats exist for
+[[sv/mv.swizzle]] and [[sv/mv.vec]] when Pack/Unpack is enabled.
+
# Pseudocode
// instruction fields:
rd = get_rt_field(); // bits 6..10
ra = get_ra_field(); // bits 11..15
- vc = get_vc_field(); // bit 22
vf = get_vf_field(); // bit 23
vs = get_vs_field(); // bit 24
ms = get_ms_field(); // bit 25
if vf and not vs and not ms {
// increment src/dest step mode
// NOTE! this is in no way complete! predication is not included
- // and neither is SUB-VL mode
+ // and neither is SUBVL mode
srcstep = SPR[SV].srcstep
dststep = SPR[SV].dststep
VL = SPR[SV].VL
// write CR? helps for doing Vertical loops, detects end
// of Vector Elements
- if Rc {
+ if Rc = 1 {
// update CR to indicate that srcstep/dststep "rolled over"
CR0.eq = rollover
}
// 4 options: from SPR, from immed, from ra, from CTR
if vs {
// VL to be sourced from fields/regs
- if vc {
- VL = CTR
- } else if ra != 0 {
+ if ra != 0 {
VL = GPR[ra]
} else {
VL = vlimmed
regs[rt] = VL;
}
// write CR?
- if Rc {
+ if Rc = 1 {
// update CR from VL (not rt)
CR0.eq = (VL == 0)
...
end:
blr
-## setmvlhi double loop
-
-Two elements per inner loop are executed per instruction. This assumes
-that underlying hardware, when `setmvlhi` requests a parallelism hint of 2
-actually sets a parallelism hint of 2.
-
-This example, in c, would be:
-
-```
-long *r4;
-for (i=0; i < CTR; i++)
-{
- r4[i+2] += r4[i]
-}
-```
-
-where, clearly, it is not possible to do more
-than 2 elements in parallel at a time: attempting
-to do so would result in data corruption. The compiler
-may be able to determine memory aliases and inform
-hardware at runtime of the maximum safe parallelism
-limit.
-
-Whilst this example could be simplified to simply set VL=2,
-or exploit the fact that overlapping adds have well-defined
-behaviour, this has not been done, here, for illustrative purposes
-in order to demonstrate setmvhli and Vertical-First Mode.
-
-Note, crucially, how r4, r32 and r20 are **NOT** incremented
-inside the inner loop. The MAXVL reservation is still 8,
-i.e. as srcstep and dststep advance (by 2 elements at a time)
-registers r20-r27 will be used for the first LD, and
-registers r32-39 for the second LD. `r4+srcstep*8` will be used
-as the elstrided offset for LDs.
-
-```
- setmvlhi 8, 2 # MVL=8, VFHint=2
-loop:
- setvl r1, CTR, vf=1 # VL=r1=MAX(MVL, CTR), VF=1
- mulli r1, r1, 8 # multiply by int width
-loopinner:
- sv.ld r20.v, r4(0) # load VLhint elements (max 2)
- addi r2, r4, 16 # 2 elements ahead
- sv.ld r32.v, r2(0) # load VLhint elements (max 2)
- sv.add r32.v, r20.v, r32.v # x[i+2] += x[i]
- sv.st r32.v, r2(0) # store VLhint elements
- svstep. # srcstep += VLhint
- bnz loopinner # repeat until srcstep=VL
- # now done VL elements, move to next batch
- add r4, r4, r1 # move r4 pointer forward
- sv.bnz/ctr loop # decrement CTR by VL
-```