Data movement within the register file — from single-element scalar taps to full crossbar shuffles.
| Semantics & rules | |
|---|---|
| vmv.x.s / vmv.s.x — and vfmv.f.s / vfmv.s.f | Element 0 ↔ scalar register taps; LMUL ignored. |
| vslideup .vx/.vi | vd[i+OFFSET] = vs2[i]; elements below max(vstart, OFFSET) unchanged. Destination may NOT overlap source (WAR hazard + restartability) — reserved otherwise. |
| vslidedown .vx/.vi | vd[i] = vs2[i+OFFSET], reading 0 past VLMAX; overlap allowed. Power-of-2 offsets may be fast-pathed. |
| vslide1up / vslide1down (+ vfslide1up/down) | Slide by one AND insert a scalar (x/f) at the vacated end (element 0 for up, vl−1 for down) — the recurrence and sliding-window primitive. |
| vrgather.vv / vrgatherei16.vv / .vx / .vi | vd[i] = (index ≥ VLMAX) ? 0 : vs2[index] — the general gather. ei16 fixes index EEW at 16 bits (SEW=8 indices can’t span long vectors; SEW=64 indices waste bits; 16 always suffices since VLMAX ≤ 65536). .vx/.vi broadcast one element. No source overlap. |
| vcompress.vm | Pack vs2’s elements selected by mask vs1 densely into vd’s low elements, order preserved. Always unmasked; vstart must be 0; no overlap with either source. |
| vmv1r.v / vmv2r.v / vmv4r.v / vmv8r.v | Whole-register copies (like the whole-register loads: vtype-independent), aligned power-of-2 counts. |
The compaction pattern, closing the loop from the mask page:
vmslt.vx v0, v8, t0 # select: elements < threshold
vcompress.vm v16, v8, v0 # pack survivors densely
vcpop.m t1, v0 # how many survived
vsetvli x0, t1, e32, m1, ta, ma
vse32.v v16, (a2) # store the packed result
Hardware Designer Notes
vrgather throughput is the classic vector-unit differentiator: element-serial (cheap, slow), SEW-grouped banks (middle), or full crossbar (fast, quadratic wiring). Decide by workload — sorting and AI tokenization lean on gathers; scientific kernels mostly don’t.
Minimal Linux-boot hart MUST
- Enforce the overlap reservations (slideup, gather, compress) and vcompress’s vstart=0 rule
- Implement vrgather’s out-of-range-reads-zero and the ei16 index decoupling
- Keep the scalar-tap asymmetry exact: reads fire at vl=0, writes don’t
MAY simplify / trap-and-emulate
- Implement vrgather iteratively (element per cycle) on narrow datapaths — correct, and honest about the crossbar you didn’t build
- Fast-path power-of-2 slide offsets and slide1 as dedicated boundary muxes
- Sequence vcompress with a running-popcount pointer — one pass, no crossbar needed
Check yourself — permutation instructions
1.Why is vslideup's destination forbidden from overlapping its source?
2.What distinguishes vrgather.vv from vrgatherei16.vv, and why does the latter exist?
3.What does vcompress.vm do, and what are its unusual restrictions?
4.Why do vslide1up/vslide1down (and vf variants) exist when vslideup/down cover any offset?