The five memory-access families, from fastest to most flexible:
| Behavior & fine print | |
|---|---|
| vle8/16/32/64.v · vse*.v — unit-stride | Contiguous from (rs1), data EEW in the mnemonic. The performance path. |
| vlm.v / vsm.v — mask transfer | Byte moves of evl = ceil(vl/8) bytes (one bit per element!), EMUL=1, always tail-agnostic, vstart in bytes. Encoded as EEW=8 with special lumop/sumop. |
| vlse*.v / vsse*.v — constant stride | Element i at (rs1) + i·x[rs2]; zero and negative strides legal; element accesses unordered. |
| vluxei/vloxei/vsuxei/vsoxei — indexed (gather/scatter) | Address = (rs1) + vs2[i] byte offsets; index EEW in the mnemonic (ei8..ei64), data at SEW. U = unordered; O = ordered (per-element ordering for non-idempotent targets and overlapping scatters). |
| vle*ff.v — fault-only-first | Unit-stride load that traps ONLY on element-0 exceptions; a fault at element k>0 instead truncates vl to k. The while-loop vectorizer. |
| vlseg/vsseg (+ strided/indexed forms) — segments | Move NFIELDS (= nf+1 ≤ 8) contiguous fields per segment into consecutive register groups: vlseg3e8.v de-interleaves RGB into v8/v9/v10. vl counts segments; masking per segment; EMUL·NFIELDS ≤ 8; no wrap past v31; vstart in segments. |
Fault-only-first: vectorizing while
# strlen(str): probe a full strip, let faults shorten it
loop:
vsetvli a1, x0, e8, m8, ta, ma # vl = VLMAX
vle8ff.v v8, (a0) # may TRUNCATE vl, never faults past elem 0
csrr a1, vl # actual elements loaded
vmseq.vi v0, v8, 0 # find NUL
vfirst.m a2, v0
...
Element 0 still faults normally — guaranteeing progress — and a
truncated vl feeds the loop exactly like a short final strip.
(vl changes by FOF are one of only two writers of vl, alongside
vset{i}vl{i}.)
Hardware Designer Notes
The FOF truncation path is the trickiest verification target in vector memory: fault reporting must be precise at element granularity but suppressed architecturally. Model it as “speculative-past-element-0” from day one and the trap logic falls out naturally.
Minimal Linux-boot hart MUST
- Give FOF loads a non-faulting probe path: element-0 exceptions trap normally, later ones must squash and truncate vl — this needs the MMU response to flow back before architectural commit of vl
- Honor ordered-indexed element ordering (effectively serialize) and the unordered license everywhere else
- Enforce the segment reserved cases: EMUL·NFIELDS > 8 and register-number wrap past 31
MAY simplify / trap-and-emulate
- Crack segments into field-wise micro-ops; a 3-field byte segment load is a natural 3-pass strided sequence with register-file transpose
- Optimize away redundant x0-stride accesses (idempotent regions) — the explicit architectural license
Check yourself — vector memory instructions
1.vle32ff.v hits a page fault at element 5 (element 0 was fine). What happens?
2.What does vlseg3e8.v v8, (a0) do with packed RGB pixel data?
3.How do vlse64.v with x[rs2]=0 and the same instruction with rs2=x0 differ?
4.Why do vlm.v/vsm.v (mask loads/stores) use evl = ceil(vl/8)?