VIOTA.M

RISC-V VIOTA.M Instruction Details

Instruction ManualOPMVV

Counts active set bits in the source mask before each element and writes the prefix count to integer vector vd.

Instruction Syntax

viota.m vd, vs2, vm
Operand Breakdown
vd is an SEW-wide integer vector group; vs2 is one mask register with one bit per element. vd cannot overlap vs2, and a masked vd cannot overlap v0.
Syntax is viota.m vd, vs2[, v0.t]; omitting v0.t gives vm=1 and including it gives vm=0. With vs2=v0, source and execution mask must contain identical bits.
Active element i receives the number of enabled set bits in vs2 below index i, excluding the current bit. Zero-extend to SEW, retaining only low SEW bits on overflow.
Require enabled V, valid vtype and vstart=0; nonzero vstart raises illegal-instruction. Traps report vstart=0 and resume from the beginning. VL=0 leaves destinations unchanged; inactive/tail follow vma/vta.
VVector PermutationMask Operations

Instruction Behavior

VIOTA.M is the RISC-V V mask-iota instruction. For each active body element i, it counts enabled set bits in vs2 at lower indexes and writes the prefix count to vd[i]. It can be combined with indexed stores to implement vector compression.

VIOTA.M Decode And Execute Animation

Starts from OP-V encoding fields, then shows how VIOTA.M writes the number of earlier active set bits into an integer vector.

Instruction input
viota.m
Execution context
vstart0VIOTA.M requires vstart=0; a nonzero value raises an illegal-instruction exception

The teaching model fixes vstart=0. VIOTA.M raises an illegal-instruction exception for nonzero vstart and restarts from the beginning after trap return. Results are zero-extended for wider SEW, and only the low SEW bits are retained on overflow.

Teaching context: SEW=32, LMUL=m1, VLEN=4096, VLMAX=128, vstart=0, valid vtype, enabled VS, and ta/ma. At most 64 elements are shown; prefix counts do not exceed 63, so no SEW truncation occurs. x marks masked-off destinations, which may retain old values or become all ones; tails follow ta. VL=0 updates no destinations, including tails; normal completion resets vstart=0.

OP-V encodingfunct6 | vm | vs2 | vs1=10000 | funct3 | vd | opcode
funct6
010100
vm
0
vs2
01000
vs1
10000
funct3
010
vd
01100
opcode
1010111
lane
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v8
0
0
1
0
1
0
1
0
0
1
0
0
1
0
0
1
v0.t
1
0
1
1
1
1
0
1
1
1
1
0
1
1
1
1
scan
0
off
0
1
1
2
off
2
2
2
3
off
3
4
4
4
v12
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Current step

Show OP-V 32-bit encoding fields

viota.m uses OP-V encoding; the vs1 field is fixed to 10000, and vs1 is not a syntax operand.

This animation shows only ISA-visible relationships from the official V extension: OP-V field decode, active mask-bit scan within vl, and destination integer-vector writeback. It does not model pipelines, caches, or timing.

Quick Understanding & Search Notes

VIOTA.M turns a mask into integer indexes by asking each active lane how many selected 1 bits appear before it; the current lane itself is not counted.

Official syntax is `viota.m vd, vs2, vm`; OP-V VMUNARY0 encoding uses `funct6=010100`, `funct3=010`, `vs1=10000`, and vs2 supplies source mask bits.
For active body element i, the result is the number of active set bits in vs2 at indexes less than i; the current element itself is excluded from that lane count.
With vm=0, v0.t determines which elements participate; elements with v0.t=0 do not increment prefix counts for later lanes.
Destination vd receives SEW-wide integer results; if a count exceeds the SEW representation, only the low SEW bits are retained.
vstart must be 0 and resets to 0 after normal completion. VL=0 updates no destination elements. Masked-off and tail elements follow vma/vta; they are not guaranteed zeros.

Vector Execution Context

vd is an SEW-wide integer vector group; vs2 is one mask register with one bit per element. vd cannot overlap vs2, and a masked vd cannot overlap v0.

Syntax is viota.m vd, vs2[, v0.t]; omitting v0.t gives vm=1 and including it gives vm=0. With vs2=v0, source and execution mask must contain identical bits.

Active element i receives the number of enabled set bits in vs2 below index i, excluding the current bit. Zero-extend to SEW, retaining only low SEW bits on overflow.

Require enabled V, valid vtype and vstart=0; nonzero vstart raises illegal-instruction. Traps report vstart=0 and resume from the beginning. VL=0 leaves destinations unchanged; inactive/tail follow vma/vta.

The RISC-V Instruction Set Manual, Volume I: Unprivileged Architecture — Version 20260120, Chapter 31

Common Usage Scenarios

Sparse Indexing

Assume enabled V/VS, valid e32,m1, VLMAX≥4, AVL=4, and vl=4, vstart=0, ta/ma after vsetvli; destination does not overlap source masks. Count earlier enabled set bits: vs2 bits=[1,0,1,1], v0=[1,0,1,1] → vd=[0,agnostic,1,2]. Agnostic elements may retain old values or become all ones, without guaranteed zeros.

Compress Helper

Assume enabled V/VS, valid e32,m1, VLMAX≥4, AVL=4, and vl=4, vstart=0, ta/ma after vsetvli; destination does not overlap source masks. Count earlier enabled set bits: vs2 bits=[1,0,1,1], v0=[1,0,1,1] → vd=[0,agnostic,1,2]. Agnostic elements may retain old values or become all ones, without guaranteed zeros.

Conditional Gather

Assume enabled V/VS, valid e32,m1, VLMAX≥4, AVL=4, and vl=4, vstart=0, ta/ma after vsetvli; destination does not overlap source masks. Count earlier enabled set bits: vs2 bits=[1,0,1,1], v0=[1,0,1,1] → vd=[0,agnostic,1,2]. Agnostic elements may retain old values or become all ones, without guaranteed zeros.

Pre-Use Checklist

Syntax Check
  • vd is an SEW-wide integer vector group; vs2 is one mask register with one bit per element. vd cannot overlap vs2, and a masked vd cannot overlap v0.
  • Syntax is viota.m vd, vs2[, v0.t]; omitting v0.t gives vm=1 and including it gives vm=0. With vs2=v0, source and execution mask must contain identical bits.
Semantic Check
  • Active element i receives the number of enabled set bits in vs2 below index i, excluding the current bit. Zero-extend to SEW, retaining only low SEW bits on overflow.
  • Require enabled V, valid vtype and vstart=0; nonzero vstart raises illegal-instruction. Traps report vstart=0 and resume from the beginning. VL=0 leaves destinations unchanged; inactive/tail follow vma/vta.

Pitfalls / Common Confusions

vs2 is the bit view of a mask register, not a normal SEW-wide integer vector; the output vd is the SEW-wide integer vector.
The count covers participating elements before the current lane: active set bits with indexes less than i, excluding the current lane itself.
With vm=0, elements whose v0.t bit is 0 do not contribute to the prefix count. Their destinations follow mask policy: mu preserves old values; ma permits old values or all ones.
If the prefix count is not representable in the current SEW, the low SEW bits are written; choose an SEW large enough for counts within vl in normal examples.
Overlap between destination vd and source vs2, or between vd and v0 during masked execution, is a reserved form; examples and animation avoid these combinations.
vstart must be 0; a nonzero value raises an illegal-instruction exception. Other traps report vstart=0 and resume from the beginning.

FAQ

Does VIOTA.M include the current lane bit in its result?

No. Lane i counts only active set bits at lower indexes, so the first active element receives 0.

Is VIOTA.M output still a mask?

No. vs2 is a mask-bit input, but vd is an integer vector result; each active element receives a SEW-wide prefix count.

Do lanes disabled by v0.t affect later prefix counts?

No. With vm=0, only elements whose v0.t bit is 1 participate in iota counting and writeback; disabled lanes do not increment later counts.