Five EmbedDev logo Five EmbedDev

An Embedded RISC-V Blog
RISC-V Base Vector Extension , 0.7.1 2019/06/10

Contributors include: Alon Amid, Krste Asanovic, Allen Baum, Alex Bradbury, Tony Brewer, Chris Celio, Aliaksei Chapyzhenka, Silviu Chiricescu, Ken Dockser, Bob Dreyer, Roger Espasa, Sean Halle, John Hauser, David Horner, Bruce Hoult, Bill Huffman, Constantine Korikov, Ben Korpan, Robin Kruppe, Yunsup Lee, Guy Lemieux, Filip Moc, Rich Newell, Albert Ou, David Patterson, Colin Schmidt, Alex Solomatnikov, Steve Wallach, Andrew Waterman, Jim Wilson.

Known issues with current version:

  • encoding needs better formatting

  • vector memory consistency model needs to be clarified

  • interaction with privileged architectures

1. Introduction

This document describes the draft of the RISC-V base vector extension. The document describes all the individual features of the base vector extension.

Note
This is a draft of a stable proposal for the vector specification to be used for implementation and evaluation. Once the draft label is removed, version 0.7 is intended to be stable enough to begin developing toolchains, functional simulators, and initial implementations, though will continue to evolve with minor changes and updates.

The term base vector extension is used informally to describe the standard set of vector ISA components. This draft spec is intended to capture how a certain vector function will be implemented as vector instructions, but to not yet determine what set of vector instructions are mandatory for a given platform.

Note
Each actual platform profile will formally specify the mandatory components of any vector extension adopted by that platform. The base vector extension can expected to be close to that which will eventually be used in the standard Unix platform profile that supports vectors. Other platforms, including embedded platforms, may choose to implement subsets of these extensions. The exact set of mandatory supported instructions for an implementation to be compliant with a given profile is subject to change until each profile spec is ratified.

The base vector extension is designed to act as a base for additional vector extensions in various domains, including cryptography and machine learning.

2. Implementation-defined Constant Parameters

Each hart supporting the vector extension defines three parameters:

  1. The maximum size of a single vector element in bits, ELEN, which must be a power of 2.

  2. The number of bits in a vector register, VLENELEN, which must be a power of 2.

  3. The striping distance in bits, SLEN, which must be VLEN ≥ SLEN ≥ 32, and which must be a power of 2.

Note
Platform profiles may set further constraints on these parameters, for example, requiring that ELEN ≥ max(XLEN,FLEN), or requiring a minimum VLEN value, or setting an SLEN value.

The ISA supports writing binary code that under certain constraints will execute portably on harts with different values for these parameters.

Note
Code can be written that will expose differences in implementation parameters.
Note
Thread contexts with active vector state cannot be migrated during execution between harts that have any difference in VLEN, ELEN, or SLEN parameters.

3. Vector Extension Programmer’s Model

The vector extension adds 32 vector registers, and five unprivileged CSRs (vstart, vxsat, vxrm, vtype, vl) to a base scalar RISC-V ISA. If the base scalar ISA does not include floating-point, then a fcsr register is also added to hold mirrors of the vxsat and vxrm CSRs as explained below.

Table 1. New vector CSRs
Address Privilege Name Description

0x008

URW

vstart

Vector start position

0x009

URW

vxsat

Fixed-Point Saturate Flag

0x00A

URW

vxrm

Fixed-Point Rounding Mode

0xC20

URO

vl

Vector length

0xC21

URO

vtype

Vector data type register

3.1. Vector Registers

The vector extension adds 32 architectural vector registers, v0-v31 to the base scalar RISC-V ISA.

Each vector register has a fixed VLEN bits of state.

Note
Zfinx ("F in X") is a new ISA option under consideration where floating-point instructions take their arguments from the integer register file. The 0.7 vector extension is also compatible with this option.

3.2. Vector type register, vtype

The read-only XLEN-wide vector type CSR, vtype provides the default type used to interpret the contents of the vector register file, and can only be updated by vsetvl{i} instructions. The vector type also determines the organization of elements in each vector register, and how multiple vector registers are grouped.

Note
Earlier drafts allowed the vtype register to be written using regular CSR writes. Allowing updates only via the vsetvl{i} instructions simplifies maintenance of the vtype register state.

In the base vector extension, the vtype register has three fields, vill, vsew[2:0], and vlmul[1:0].

Table 2. vtype register layout
Bits Name Description

XLEN-1

vill

Illegal value if set

XLEN-2:7

Reserved (write 0)

6:5

vediv[1:0]

Used by EDIV extension

4:2

vsew[2:0]

Standard element width (SEW) setting

1:0

vlmul[1:0]

Vector register group multiplier (LMUL) setting

Note
The smallest base implementation requires storage for only four bits of storage in vtype, two bits for vsew[1:0] and two bits for vlmul[1:0]. The illegal value represented by vill can be encoded using the illegal 64-bit combination in vsew[1:0] without requiring an additional storage bit.
Note
The vediv[1:0] field is used by the EDIV extension described below.
Note
Further standard and custom extensions to the vector base will extend these fields to support a greater variety of data types.
Note
It is anticipated that an extended 64-bit instruction encoding would allow these fields to be specified statically in the instruction encoding.

3.2.1. Vector standard element width vsew

The value in vsew sets the dynamic standard element width (SEW). By default, a vector register is viewed as being divided into VLEN / SEW standard-width elements. In the base vector extension, only SEW up to max(XLEN,FLEN) are required to be supported.

Table 3. vsew[2:0] (standard element width) encoding
vsew[2:0] SEW

0

0

0

8

0

0

1

16

0

1

0

32

0

1

1

64

1

0

0

128

1

0

1

256

1

1

0

512

1

1

1

1024

Table 4. Example VLEN = 128 bits
SEW Elements per vector register

64

2

32

4

16

8

8

16

3.2.2. Vector Register Grouping (vlmul)

Multiple vector registers can be grouped together to form a vector register group, so that a single vector instruction can operate on multiple vector registers. Vector register groups allow double-width or larger elements to be operated on with the same vector length as standard-width elements. Vector register groups also provide greater execution efficiency for longer application vectors.

The number of vector registers in a group, LMUL, is an integer power of two set by the vlmul field in vtype (LMUL = 2vlmul[1:0]).

The derived value VLMAX = LMUL*VLEN/SEW represents the maximum number of elements that can be operated on with a single vector instruction given the current SEW and LMUL settings.

vlmul LMUL #groups VLMAX Grouped registers

0

0

1

32

VLEN/SEW

vn (no group)

0

1

2

16

2*VLEN/SEW

vn, vn+1

1

0

4

8

4*VLEN/SEW

vn, …​, vn+3

1

1

8

4

8*VLEN/SEW

vn, …​, vn+7

When vlmul=01, then vector operations on register v n also operate on vector register v n+1, giving twice the vector length in bits. Instructions specifying a vector operand with an odd-numbered vector register will raise an illegal instruction exception.

Similarly, when vlmul=10, vector instructions operate on four vector registers at a time, and instructions specifying vector operands using vector register numbers that are not multiples of four will raise an illegal instruction exception. When vlmul=11, operations operate on eight vector registers at a time, and instructions specifying vector operands using register numbers that are not multiples of eight will raise an illegal instruction exception.

Note
This grouping pattern (LMUL=8 has groups v0,v8,v16,v24) was adopted in 0.6 initially to avoid issues with the floating-point calling convention when floating-point values were overlaid on the vector registers, whereas earlier versions kept the vector register group names contiguous (LMUL=8 has groups v0, v1, v2, v3). In v0.7, the floating-point registers are separate again.

Mask register instructions always operate on a single vector register, regardless of LMUL setting.

3.2.3. Vector Type Illegal vill

The vill bit is used to encode that a previous vsetvl{i} instruction attempted to write an unsupported value to vtype.

Note
The vill bit is held in bit XLEN-1 of the CSR to support checking for illegal values with a branch on the sign bit.

If the vill bit is set, then any attempt to execute a vector instruction (other than a vector configuration instruction) will raise an illegal instruction exception.

When the vill bit is set, the other XLEN-1 bits in vtype shall be zero.

3.3. Vector Length Register vl

The XLEN-bit-wide read-only vl CSR can only be updated by the vsetvli and vsetvl instructions, and the fault-only-first vector load instruction variants.

The vl register holds an unsigned integer specifying the number of elements to be updated by a vector instruction. Elements in any destination vector register group with indices ≥ vl are zeroed during execution of a vector instruction. When vstartvl, no elements are updated in any destination vector register group.

Note
As a consequence, when vl=0, no elements are updated in the destination vector register group, regardless of vstart.
Note
The number of bits implemented in vl depends on the implementation’s maximum vector length of the smallest supported type. The smallest vector implementation, RV32IV, would need at least six bits in vl to hold the values 0-32 (with VLEN=32, LMUL=8 and SEW=8 results in VLMAX of 32).

3.4. Vector Start Index CSR vstart

The vstart read-write CSR specifies the index of the first element to be executed by a vector instruction.

Normally, vstart is only written by hardware on a trap on a vector instruction, with the vstart value representing the element on which the trap was taken (either a synchronous exception or an asynchronous interrupt), and at which execution should resume after a resumable trap is handled.

All vector instructions are defined to begin execution with the element number given in the vstart CSR, leaving earlier elements in the destination vector undisturbed, and to reset the vstart CSR to zero at the end of execution.

Note
All vector instructions, including vsetvl{i}, reset the vstart CSR to zero.

If the value in the vstart register is greater than or equal to the vector length vl then no element operations are performed, nor are the elements at the end of the destination vector past vl zeroed. The vstart register is then reset to zero.

The vstart CSR is defined to have only enough writable bits to hold the largest element index (one less than the maximum VLMAX) or lg2(VLEN) bits. The upper bits of the vstart CSR are hardwired to zero (reads zero, writes ignored).

Note
The maximum vector length is obtained with the largest LMUL setting (8) and the smallest SEW setting (8), so VLMAX_max = 8*VLEN/8 = VLEN. For example, for VLEN=256, vstart would have 8 bits to represent indices from 0 through 255.

The vstart CSR is writable by unprivileged code, but non-zero vstart values may cause vector instructions to run substantially slower on some implementations, so vstart should not be used by application programmers. A few vector instructions can not be executed with a non-zero vstart value and will raise an illegal instruction exception as defined below.

Implementations are permitted to raise illegal instruction exceptions when attempting to execute a vector instruction with a value of vstart that the implementation can never produce when executing that same instruction with the same vtype setting.

Note
For example, some implementations will never take interrupts during execution of a vector arithmetic instruction, instead waiting until the instruction completes to take the interrupt. Such implementations are permitted to raise an illegal instruction exception when attempting to execute a vector arithmetic instruction when vstart is nonzero.

3.5. Vector Fixed-Point Rounding Mode Register vxrm

The vector fixed-point rounding-mode register holds a two-bit read-write rounding-mode field. The vector fixed-point rounding-mode is given a separate CSR address to allow independent access, but is also reflected as a field in the upper bits of fcsr. Systems without floating-point must add fcsr when adding the vector extension.

Table 5. vxrm encoding
Bits [1:0] Abbreviation Rounding Mode

0

0

rnu

round-to-nearest-up (add +0.5 LSB)

0

1

rne

round-to-nearest-even

1

0

rdn

round-down (truncate)

1

1

rod

round-to-odd (OR bits into LSB, aka "jam")

Bits[XLEN-1:2] should be written as zeros.

Note
The rounding mode can be set with a single csrwi instruction.

3.6. Vector Fixed-Point Saturation Flag vxsat

The vxsat CSR holds a single read-write bit that indicates if a fixed-point instruction has had to saturate an output value to fit into a destination format.

The vxsat bit is mirrored in the upper bits of fcsr.

3.7. Vector Fixed-Point Fields in fcsr

The vxrm and vxsat separate CSRs can also be accessed via fields in the floating-point CSR, fcsr. The fcsr register must be added to systems without floating-point that add a vector extension.

Table 6. fcsr layout
Bits Name Description

10:9

vxrm

Fixed-point rounding mode

8

vxsat

Fixed-point accrued saturation flag

7:5

frm

Floating-point rounding mode

4:0

fflags

Floating-point accrued exception flags

Note
The fields are packed into fcsr to make context-save/restore faster.

3.8. State of Vector Extension at Reset

The vector extension must have a consistent state at reset. In particular, vtype and vl must have values that can be read and then restored with a single vsetvl instruction.

Note
It is recommended that at reset, vtype.vill is set, the remaining bits in vtype are zero, and vl is set to zero.

The vstart, vxrm, vxsat CSRs can have arbitrary values at reset.

Note
Any use of the vector unit will require an initial vsetvl{i}, which will reset vstart. The `vxrm and vxsat fields should be reset explicitly in software before use.

The vector registers can have arbitrary values at reset.

4. Mapping of Vector Elements to Vector Register State

The following diagrams illustrate how different width elements are packed into the bytes of a vector register depending on the current SEW and LMUL settings, as well as implementation ELEN and VLEN. Elements are packed into each vector register with the least-significant byte in the lowest-numbered bits.

Note
Previous RISC-V vector proposals (< 0.6) hid this mapping from software, whereas this proposal has a specific mapping for all configurations, which reduces implementation flexibility but removes need for zeroing on config changes. Making the mapping explicit also has the advantage of simplifying oblivious context save-restore code, as the code can save the configuration in vl and vtype, then reset vtype to a convenient value (e.g., four vector groups of LMUL=8, SEW=ELEN) before saving all vector register bits without needing to parse the configuration. The reverse process will restore the state.

4.1. Mapping with LMUL=1

When LMUL=1, elements are simply packed in order from the least-significant to most-significant bits of the vector register.

Note
To increase readability, vector register layouts are drawn with bytes ordered from right to left with increasing byte address. Bits within an element are numbered in a little-endian format with increasing bit index from right to left corresponding to increasing magnitude.
  The element index is given in hexadecimal and is shown placed at the least-significant byte of the stored element. ELEN <=128 and LMUL=1 throughout.


 VLEN=32b

 Byte         3 2 1 0

 SEW=8b       3 2 1 0
 SEW=16b        1   0
 SEW=32b            0

 VLEN=64b

 Byte        7 6 5 4 3 2 1 0

 SEW=8b      7 6 5 4 3 2 1 0
 SEW=16b       3   2   1   0
 SEW=32b           1       0
 SEW=64b                   0

 VLEN=128b

 Byte        F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b      F E D C B A 9 8 7 6 5 4 3 2 1 0
 SEW=16b       7   6   5   4   3   2   1   0
 SEW=32b           3       2       1       0
 SEW=64b                   1               0
 SEW=128b                                  0

 VLEN=256b

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b   1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 SEW=16b     F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0
 SEW=32b         7       6       5       4       3       2       1       0
 SEW=64b                 3               2               1               0
 SEW=128b                                1                               0

4.2. Mapping with LMUL > 1

When vector registers are grouped, the elements of the vector register group are striped across the constituent vector registers. The striping distance in bits, SLEN, sets how many bits are packed contiguously into one vector register before moving to the next in the group.

For example, when SLEN = 128, the striping pattern is repeated in multiples of 128 bits. The first 128/SEW elements are packed contiguously at the start of the first vector register in the group. The next 128/SEW elements are packed contiguously at the start of the next vector register in the group. After packing the first LMUL*128/SEW elements at the start of each of the LMUL vector registers in the group, the second LMUL*128/SEW group of elements are packed into the second 128b segment of each of the vector registers in the group, and so on.

 Example 1: VLEN=32b, SEW=16b, LMUL=2

 Byte         3 2 1 0
 v2*n           1   0
 v2*n+1         3   2

 Example 2: VLEN=64b, SEW=32b, LMUL=2

 Byte         7 6 5 4 3 2 1 0
 v2*n               1       0
 v2*n+1             3       2

 Example 3: VLEN=128b, SEW=32b, LMUL=2

 Byte        F E D C B A 9 8 7 6 5 4 3 2 1 0
 v2*n              3       2       1       0
 v2*n+1            7       6       5       4

 Example 4: VLEN=256b, SEW=32b, LMUL=2

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 v2*n            B       A       9       8       3       2       1       0
 v2*n+1          F       E       D       C       7       6       5       4

If SEW > SLEN, the striping pattern places one element in each vector register in the group before moving to the next vector register in the group. So, when LMUL=2, the even-numbered vector register contains the even-numbered elements of the vector and the odd-numbered vector register contains the odd-numbered elements of the vector.

Note
In most implementations, the striping distance SLEN ≥ ELEN.
 Example: VLEN=256b, SEW=256b, LMUL=2

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 v2*n                                                                    0
 v2*n+1                                                                  1

When LMUL = 4, four vector registers hold elements as shown:

 Example 1: VLEN=32b, SLEN=32b, SEW=16b, LMUL=4,

 Byte         3 2 1 0
 v4*n           1   0
 v4*n+1         3   2
 v4*n+2         5   4
 v4*n+3         7   6

 Example 2: VLEN=64b, SLEN=64b, SEW=32b, LMUL=4

 Byte         7 6 5 4 3 2 1 0
 v4*n               1       0
 v4*n+1             3       2
 v4*n+2             5       4
 v4*n+3             7       6


 Example 3: VLEN=128b, SLEN=64b, SEW=32b, LMUL=4

 Byte          F E D C B A 9 8 7 6 5 4 3 2 1 0
 v4*n                9       8       1       0   32b elements
 v4*n+1              B       A       3       2
 v4*n+2              D       C       5       4
 v4*n+3              F       E       7       6

 Example 4: VLEN=128b, SLEN=128b, SEW=32b, LMUL=4

 Byte          F E D C B A 9 8 7 6 5 4 3 2 1 0
 v4*n                3       2       1       0   32b elements
 v4*n+1              7       6       5       4
 v4*n+2              B       A       9       8
 v4*n+3              F       E       D       C

 Example 5: VLEN=256b, SLEN=128b, SEW=32b, LMUL=4

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 v4*n           13      12      11      10       3       2       1       0
 v4*n+1         17      16      15      14       7       6       5       4
 v4*n+2         1B      1A      19      18       B       A       9       8
 v4*n+3         1F      1E      1D      1C       F       E       D       C

 Example 6: VLEN=256b, SLEN=128b, SEW=256b, LMUL=4

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 v4*n                                                                    0
 v4*n+1                                                                  1
 v4*n+2                                                                  2
 v4*n+3                                                                  3

A similar pattern is followed for LMUL = 8.

 Example: VLEN=256b, SLEN=128b, SEW=32b, LMUL=8

 Byte   1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 v8*n         23      22      21      20       3       2       1       0
 v8*n+1       27      26      25      24       7       6       5       4
 v8*n+2       2B      2A      29      28       B       A       9       8
 v8*n+3       2F      2E      2D      2C       F       E       D       C
 v8*n+4       33      32      31      30      13      12      11      10
 v8*n+5       37      36      35      34      17      16      15      14
 v8*n+6       3B      3A      39      38      1B      1A      19      18
 v8*n+7       3F      3E      3D      3C      1F      1E      1D      1C

Different striping patterns are architecturally visible, but software can be written that produces the same results regardless of striping pattern. The primary constraint is to not change the LMUL used to access values held in a vector register group (i.e., do not read values with a different LMUL than used to write values to the group).

Note
The striping length SLEN for an implementation is set to optimize the tradeoff between datapath wiring for mixed-width operations and buffering needed to corner-turn wide vector unit-stride memory accesses into parallel accesses for the vector register file.
Note
The previous explicit configuration design allowed these tradeoffs to be managed at the microarchitectural level and optimized for each configuration.

4.3. Mapping across Mixed-Width Operations

The pattern used to map elements within a vector register group is designed to reduce datapath wiring when supporting operations across multiple element widths. The recommended software strategy in this case is to modify vtype dynamically to keep SEW/LMUL constant (and hence VLMAX constant).

The following example shows four different packed element widths (8b, 16b, 32b, 64b) in a VLEN=256b/SLEN=128b implementation. The vector register grouping factor (LMUL) is increased by the relative element size such that each group can hold the same number of vector elements (32 in this example) to simplify stripmining code. Any operation between elements with the same index only touches operand bits located within the same 128b portion of the datapath.

 VLEN=256b, SLEN=128b
 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b, LMUL=1, VLMAX=32

 v1       1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=16b, LMUL=2, VLMAX=32

 v2*n       17  16  15  14  13  12  11  10   7   6   5   4   3   2   1   0
 v2*n+1     1F  1E  1D  1C  1B  1A  19  18   F   E   D   C   B   A   9   8

 SEW=32b, LMUL=4, VLMAX=32

 v4*n           13      12      11      10       3       2       1       0
 v4*n+1         17      16      15      14       7       6       5       4
 v4*n+2         1B      1A      19      18       B       A       9       8
 v4*n+3         1F      1E      1D      1C       F       E       D       C

 SEW=64b, LMUL=8, VLMAX=32

 v8*n                   11              10               1               0
 v8*n+1                 13              12               3               2
 v8*n+2                 15              14               5               4
 v8*n+3                 17              16               7               6
 v8*n+4                 19              18               9               8
 v8*n+5                 1B              1A               B               A
 v8*n+6                 1D              1C               D               C
 v8*n+7                 1F              1E               F               E

Larger LMUL settings can also used to simply increase vector length to reduce instruction fetch and dispatch overheads, in cases where fewer logical vector registers are required.

The following table shows each possible constant SEW/LMUL operating point for loops with mixed-width operations.

       Numbers in columns are LMUL values, and each column
       represents constant SEW/LMUL operating point

 SEW/LMUL    1   2   4   8  16  32  64 128 256 512 1024

      SEW
        8    8   4   2   1
       16        8   4   2   1
       32            8   4   2   1
       64                8   4   2   1
      128                    8   4   2   1
      256                        8   4   2   1
      512                            8   4   2   1
     1024                                8   4   2   1
Note
Larger LMUL values can cause lower datapath utilization for short vectors if SLEN is less than the spatial datapath width. In the example above with VLEN=256b, SLEN=128b, and LMUL=8, if the implementation is purely spatial with a 256b-wide vector datapath, then for an application vector length less than 17, only half of the datapath will be active. The vsetvl instructions below could have a facility added to dynamically select an appropriate LMUL according to the required application vector length (AVL) and range of element widths.
Note
Narrower machines will set SLEN to be at least as large as the datapath spatial width, so there is no need to reduce LMUL. Wider machines might set SLEN lower than the spatial datapath width to reduce wiring for mixed-width operations (e.g., width=1024, ELEN=32, SLEN=128), in which case optimizing LMUL will be important.

4.4. Mask Register Layout

A vector mask occupies only one vector register regardless of SEW and LMUL. The mask bits that are used for each vector operation depends on the current SEW and LMUL setting.

The maximum number of elements in a vector operand is:

               VLMAX = LMUL * VLEN/SEW

A mask is allocated for each element by dividing the mask register into VLEN/VLMAX fields. The size of each mask element in bits, MLEN, is:

                MLEN = VLEN/VLMAX
                     = VLEN/(LMUL * VLEN/SEW)
                     = SEW/LMUL

The size of MLEN varies from ELEN (SEW=ELEN, LMUL=1) down to 1 (SEW=8b,LMUL=8), and hence a single vector register can always hold the entire mask register.

The mask bits for element i are located in bits [MLEN*i+(MLEN-1) : MLEN*i] of the mask register. When a mask element is written by a compare instruction, the low bit in the mask element is written with the compare result and the upper bits of the mask element are zeroed. When a value is read as a mask, only the least-significant bit of the mask element is used to control masking and the upper bits are ignored. Mask elements past the end of the current vector length are zeroed.

The pattern is such that for constant SEW/LMUL values, the effective predicate bits are located in the same bit of the mask vector register, which simplifies use of masking in loops with mixed-width elements.

 VLEN=32b

          Byte    3   2   1   0
 LMUL=1,SEW=8b
                  3   2   1   0  Element
                [24][16][08][00] Mask bit position in decimal

 LMUL=2,SEW=16b
                      1       0
                    [08]    [00]
                      3       2
                    [24]    [16]

 LMUL=4,SEW=32b               0
                            [00]
                              1
                            [08]
                              2
                            [16]
                              3
                            [24]
 LMUL=2,SEW=8b
                  3   2   1   0
                [12][08][04][00]
                  7   6   5   4
                [28][24][20][16]

 LMUL=8,SEW=32b
                              0
                            [00]
                              1
                            [04]
                              2
                            [08]
                              3
                            [12]
                              4
                            [16]
                              5
                            [20]
                              6
                            [24]
                              7
                            [28]

 LMUL=8,SEW=8b
                  3   2   1   0
                [03][02][01][00]
                  7   6   5   4
                [07][06][05][04]
                  B   A   9   8
                [11][10][09][08]
                  F   E   D   C
                [15][14][13][12]
                 13  12  11  10
                [19][18][17][16]
                 17  16  15  14
                [23][22][21][20]
                 1B  1A  19  18
                [27][26][25][24]
                 1F  1E  1D  1C
                [31][30][29][28]
 VLEN=256b, SLEN=128b
 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b, LMUL=1, VLMAX=32

 v1       1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
        [248]          ...            [128] ...[96] ...[64] ...[32] ... [0] Mask bit positions in decimal

 SEW=16b, LMUL=2, VLMAX=32

 v2*n       17  16  15  14  13  12  11  10   7   6   5   4   3   2   1   0
          [184]          ...          [128]    ...     [32]    ...      [0]
 v2*n+1     1F  1E  1D  1C  1B  1A  19  18   F   E   D   C   B   A   9   8
          [248]          ...          [196]    ...     [96]    ...     [64]

 SEW=32b, LMUL=4, VLMAX=32

 v4*n           13      12      11      10       3       2       1       0
              [152]        ...        [128]    [24]        ...          [0]
 v4*n+1         17      16      15      14       7       6       5       4
              [184]        ...        [160]    [56]        ...         [32]
 v4*n+2         1B      1A      19      18       B       A       9       8
              [116]        ...        [192]    [88]        ...         [64]
 v4*n+3         1F      1E      1D      1C       F       E       D       C
              [248]        ...        [224]   [120]        ...         [96]

 SEW=64b, LMUL=8, VLMAX=32

 v8*n                   11              10               1               0
                      [136]           [128]             [8]             [0]
 v8*n+1                 13              12               3               2
                      [152]           [144]            [24]            [16]
 v8*n+2                 15              14               5               4
                      [168]           [160]            [40]            [32]
 v8*n+3                 17              16               7               6
                      [184]           [176]            [56]            [48]
 v8*n+4                 19              18               9               8
                      [200]           [192]            [72]            [64]
 v8*n+5                 1B              1A               B               A
                      [216]           [208]            [88]            [80]
 v8*n+6                 1D              1C               D               C
                      [232]           [224]           [104]            [96]
 v8*n+7                 1F              1E               F               E
                      [248]           [240]           [120]           [112]

5. Vector Instruction Formats

The instructions in the vector extension fit under four existing major opcodes (LOAD-FP, STORE-FP, AMO) and one new major opcode (OP-V).

Vector loads and stores are encoding within the scalar floating-point load and store major opcodes (LOAD-FP/STORE-FP). The vector load and store encodings repurpose a portion of the standard scalar floating-point load/store 12-bit immediate field to provide further vector instruction encoding, with bit 25 holding the standard vector mask bit (see Mask Encoding).

Format for Vector Load Instructions under LOAD-FP major opcode
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  lumop   |    rs1    | width |    vd   |0000111| VL*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |    vd   |0000111| VLS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |    vd   |0000111| VLX* indexed
  3     3     1      5           5         3         5       7

Format for Vector Store Instructions under STORE-FP major opcode
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  sumop   |    rs1    | width |   vs3   |0100111| VS*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |   vs3   |0100111| VSS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |   vs3   |0100111| VSX* indexed
  3     3     1      5           5         3         5        7
Format for Vector AMO Instructions under AMO major opcode
31    27 26  25  24      20 19       15 14   12 11      7 6     0
 amoop  |wd| vm |   vs2    |    rs1    | width | vs3/vd  |0101111| VAMO*
   5      1   1      5           5         3        5        7
Formats for Vector Arithmetic Instructions under OP-V major opcode

31       26  25   24      20 19      15 14   12 11      7 6     0
  funct6   | vm  |   vs2    |    vs1   | 0 0 0 |    vd   |1010111| OP-V (OPIVV)
  funct6   | vm  |   vs2    |    vs1   | 0 0 1 |    vd   |1010111| OP-V (OPFVV)
  funct6   | vm  |   vs2    |    vs1   | 0 1 0 |  vd/rd  |1010111| OP-V (OPMVV)
  funct6   | vm  |   vs2    |   simm5  | 0 1 1 |    vd   |1010111| OP-V (OPIVI)
  funct6   | vm  |   vs2    |    rs1   | 1 0 0 |    vd   |1010111| OP-V (OPIVX)
  funct6   | vm  |   vs2    |    rs1   | 1 0 1 |    vd   |1010111| OP-V (OPFVF)
  funct6   | vm  |   vs2    |    rs1   | 1 1 0 |  vd/rd  |1010111| OP-V (OPMVX)
     6        1        5          5        3        5        7
Formats for Vector Configuration Instructions under OP-V major opcode

 31 30         25 24      20 19      15 14   12 11      7 6     0
 0 |        zimm[10:0]      |    rs1   | 1 1 1 |    rd   |1010111| vsetvli
 1 |   000000    |   rs2    |    rs1   | 1 1 1 |    rd   |1010111| vsetvl
 1        6            5          5        3        5        7

Vector instructions can have scalar or vector source operands and produce scalar or vector results, and most vector instructions can be performed either unconditionally or conditionally under a mask.

Vector loads and stores move bit patterns between vector register elements and memory. Vector arithmetic instructions operate on values held in vector register elements.

5.1. Scalar operands

Scalar operands can be immediates, or taken from the x registers, the f registers, or element 0 of a vector register. Scalar results are written to an x or f register or to element 0 of a vector register. Any vector register can be used to hold a scalar regardless of the current LMUL setting.

Note
In a change from v0.6, the floating-point registers no longer overlay the vector registers and scalars can now come from the integer or floating-point registers. Not overlaying the f registers reduces vector register pressure, avoids interactions with the standard calling convention, simplifies high-performance scalar floating-point design, and provides compatibility with the Zfinx ISA option. Overlaying f with v would provide the advantage of lowering the number of state bits in some implementations, but complicates high-performance designs and would prevent compatibility with the Zfinx ISA option.

5.2. Vector Operands

Vector operands or results may occupy one or more vector registers depending on LMUL, but are always specified using the lowest-numbered vector register in the group. Using other than the lowest-numbered vector register to specify a vector register group will result in an illegal instruction exception.

Some vector instructions consume and produce wider-width elements and so operate on a larger vector register group than that specified in vlmul. The largest vector register group used by an instruction can not be greater than 8 vector registers, and if an vector instruction would require greater than 8 vector registers in a group, an illegal instruction exception is raised. For example, attempting a widening operation with LMUL=8 will raise an illegal instruction exception.

5.3. Vector Masking

Masking is supported on many vector instructions. Element operations that are masked off do not modify the destination vector register element and never generate exceptions.

In the base vector extension, the mask value used to control execution of a masked vector instruction is always supplied by vector register v0. Only the least-significant bit of each element of the mask vector is used to control execution.

Note
Future vector extensions may provide longer instruction encodings with space for a full mask register specifier.

The destination vector register group for a masked vector instruction can only overlap the source mask register (v0) when LMUL=1. Otherwise, an illegal vector instruction exception is raised.

Note
This constraint supports restart with a non-zero vstart value.

Other vector registers can be used to hold working mask values, and mask vector logical operations are provided to perform predicate calculations.

5.3.1. Mask Encoding

Where available, masking is encoded in a single-bit vm field in the instruction (inst[25]).

vm Description

0

vector result, only where v0[i].LSB = 1

1

unmasked

Note
In earlier proposals, vm was a two-bit field vm[1:0] that provided both true and complement masking using v0 as well as encoding scalar operations.

Vector masking is represented in assembler code as another vector operand, with .t indicating if operation occurs when v0[i].LSB is 1. If no masking operand is specified, unmasked vector execution (vm=1) is assumed.

    vop.v*    v1, v2, v3, v0.t  # enabled where v0[i].LSB=1, m=0
    vop.v*    v1, v2, v3        # unmasked vector operation, m=1
Note
Even though the base only supports one vector mask register v0 and only the true form of predication, the assembly syntax writes it out in full to be compatible with future extensions that might add a mask register specifier and supporting both true and complement masking. The .t suffix on the masking operand also helps to visually encode the use of a mask.

5.4. Prestart, Active, Inactive, Body, and Tail Element Definitions

The elements operated on during a vector instruction’s execution can be divided into four disjoint subsets.

  • The prestart elements are those whose element index is less than the initial value in the vstart register. The prestart elements do not raise exceptions and do not update the destination vector register.

  • The active elements during a vector instruction’s execution are the elements within the current vector length setting and where the current mask is enabled at that element position. The active elements can raise exceptions and update the destination vector register group.

  • The inactive elements are the elements within the current vector length setting but where the current mask is disabled at that element position. The inactive elements do not raise exceptions and do not update any destination vector register.

  • The tail elements during a vector instruction’s execution are the elements past the current vector length setting. The tail elements do not raise exceptions, but do zero the results in any destination vector register group.

  • In addition, another term, body, is used for the set of elements that are either active or inactive, i.e., after prestart but before the tail.

    for element index x
    prestart    = (0 <= x < vstart)
    mask(x)     = unmasked || v0[x].LSB == 1
    active(x)   = (vstart <= x < vl) && mask(x)
    inactive(x) = (vstart <= x < vl) && !mask(x)
    body(x)     = active(x) || inactive(x)
    tail(x)     = (vl <= x < VLMAX)

All regular vector instructions place zeros in the tail elements of the destination vector register group. Some vector arithmetic instructions are not maskable, so have no inactive elements, but still zero the tail elements.

Note
The inactive and tail update rules were designed to provide an efficient compromise between requirements of implementations with and without vector register ECC and/or renaming.
Note
Not zeroing past vl would penalize renamed implementations that would have to copy all elements past VL on every instruction execution, whereas it’s a small penalty for non-renamed implementations to implement the tail zeroing. While a renamed machine could avoid copying for whole vector registers in a group by not renaming, operations on individual registers may be deep enough that requiring full occupancy for any vector length would be problematic. Zeroing values past vl does not impact most software, except for a small cost in some reduction cases.
Note
For zeroing tail updates, implementations with temporally long vector registers, either with or without register renaming, will be motivated to add microarchitectural state to avoid actually writing zeros to all tail elements, but this is a relatively simple microarchitectural optimization. For example, one bit per element group or a quantized VL can be used to track the extent of zeroing. An element group is the set of elements comprising the smallest atomic unit of execution in the microarchitecture (often equivalent to the width of the physical datapath in the machine). The microarchitectural state for an element group indicates that zero should be returned for the element group on a read, and that zero should be substituted in for any masked-off elements in the group on the first write to that element group (after which the element group zero bit can be cleared).
Note
Providing merging predication instead of zeroing inactive elements on a masked operation reduces code path length for many code blocks, and reduces register pressure by allowing different code paths to use disjoint sets of elements in the same vector register. Implementations with vector register ECC or renaming will have to perform read-update-write on the destination register value to preserve inactive elements on arithmetic instructions, so would appear to need an extra vector register read port. However, the arithmetic instructions are designed such that the largest read-port requirement is for fused multiply-add instructions that are destructive and overwrite one source, and hence do not need an extra read port to preserve inactive elements. Given that linear algebra is one of the more important applications for vector units, and that fused multiply-add is the dominant operation in linear algebra routines, microarchitectures will be optimized for fused multiply-add operations and so should be able to preserve inactive elements on other arithmetic operations without large additional cost. However, masked vector load instructions incur the cost of an additional read port on their destination register. The need to support resumable vector loads with non-zero vstart values also drives the need to preserve vector load destination register values. The AMOs have been defined to be destructive in their source operand to reduce the maximum read port requirement for the memory pipe. An option that was considered was to have loads behave differently from arithmetic instructions and to zero any masked-off elements. However, this would require additional instructions and increase register pressure, and vector loads must in any case still cope with non-zero vstart values through some mechanism.

6. Configuration-Setting Instructions

A set of instructions are provided to allow rapid configuration of the values in vl and vtype to match application needs.

6.1. vsetvli/vsetvl instructions

 vsetvli rd, rs1, vtypei # rd = new vl, rs1 = AVL, vtypei = new vtype setting
                         # if rs1 = x0, then use maximum vector length
 vsetvl  rd, rs1, rs2    # rd = new vl, rs1 = AVL, rs2 = new vtype value
                         # if rs1 = x0, then use maximum vector length

The vsetvli instruction sets the vtype and vl CSRs based on its arguments, and writes the new value of vl into rd.

The new vtype setting is encoded in the immediate fields of vsetvli and in the rs2 register for vsetvl.

Formats for Vector Configuration Instructions under OP-V major opcode

 31 30         25 24      20 19      15 14   12 11      7 6     0
 0 |        zimm[10:0]      |    rs1   | 1 1 1 |    rd   |1010111| vsetvli
 1 |   000000    |   rs2    |    rs1   | 1 1 1 |    rd   |1010111| vsetvl
 1        6            5          5        3        5        7
Table 7. vtype register layout
Bits Name Description

XLEN-1

vill

Illegal value if set

XLEN-2:7

Reserved (write 0)

6:5

vediv[1:0]

Used by EDIV extension

4:2

vsew[2:0]

Standard element width (SEW) setting

1:0

vlmul[1:0]

Vector register group multiplier (LMUL) setting

 Suggested assembler names used for vtypei setting

 e8    #   8b elements
 e16   #  16b elements
 e32   #  32b elements
 e64   #  64b elements
 e128  # 128b elements

 m1   # Vlmul x1, assumed if m setting absent
 m2   # Vlmul x2
 m4   # Vlmul x4
 m8   # Vlmul x8

 d1   # EDIV 1, assumed if d setting absent
 d2   # EDIV 2
 d4   # EDIV 4
 d8   # EDIV 8

Examples:
    vsetvli t0, a0, e8          # SEW= 8, LMUL=1, EDIV=1
    vsetvli t0, a0, e8,m2       # SEW= 8, LMUL=2, EDIV=1
    vsetvli t0, a0, e32,m2,d4   # SEW=32, LMUL=2, EDIV=4

If the vtype setting is not supported by the implementation, then the vill bit is set in vtype, the remaining bits in vtype are set to zero, and the vl register is also set to zero.

The requested application vector length (AVL) is passed in rs1 as an unsigned integer. Using x0 as the rs1 register specifier, encodes an infinite AVL, and so requests the maximum possible vector length.

Note
A vsetvl{i} with AVL=x0 can be used to read current VLMAX, though this does overwrite vl.
Note
The behavior of vsetvl{i} does not depend on whether rd=x0. Setting rd=x0 can be useful when the application already knows what value vl will assume, e.g., when changing SEW and LMUL with constant AVL.
Note
Earlier drafts required a trap when setting vtype to an illegal value. However, this would have added the first data-dependent trap on a CSR write to the ISA. The current scheme also supports light-weight runtime interrogation of the supported vector unit configurations by checking if vill is clear for a given setting.

6.2. Constraints on Setting vl

The vsetvl{i} instructions first set VLMAX according to the vtype argument, then set vl obeying the following constraints:

  1. vl = AVL if AVL ≤ VLMAX

  2. vl ≥ ceil(AVL / 2) if AVL < (2 * VLMAX)

  3. vl = VLMAX if AVL ≥ (2 * VLMAX)

  4. Deterministic on any given implementation for same input AVL and VLMAX values

  5. These specific properties follow from the prior rules:

    1. vl = 0 if AVL = 0

    2. vl > 0 if AVL > 0

    3. vl ≤ VLMAX

    4. vl ≤ AVL

    5. a value read from vl when used as the AVL argument to vsetvl{i} results in the same value in vl, provided the resultant VLMAX equals the value of VLMAX at the time that vl was read

Note

The vl setting rules are designed to be sufficiently strict to preserve vl behavior across register spills and context swaps for AVL ≤ VLMAX, yet flexible enough to enable implementations to improve vector lane utilization for AVL > VLMAX.

For example, this permits an implementation to set vl = ceil(AVL / 2) for VLMAX < AVL < 2*VLMAX in order to evenly distribute work over the last two iterations of a stripmine loop. Requirement 2 ensures that the first stripmine iteration of reduction loops uses the largest vector length of all iterations, even in the case of AVL < 2*VLMAX. This allows software to avoid needing to explicitly calculate a running maximum of vector lengths observed during a stripmined loop.

6.3. vsetvl Instruction

The vsetvl variant operates similarly to vsetvli except that it takes a vtype value from rs2 and can be used for context restore, and when the vtypei field is too small to hold the desired setting.

Note
Several active complex types can be held in different x registers and swapped in as needed using vsetvl.

6.4. Examples

The SEW and LMUL settings can be changed dynamically to provide high throughput on mixed-width operations in a single loop.

# Example: Load 16-bit values, widen multiply to 32b, shift 32b result
# right by 3, store 32b values.

# Loop using only widest elements:

loop:
    vsetvli a3, a0, e32,m8  # Use only 32-bit elements
    vlh.v v8, (a1)          # Sign-extend 16b load values to 32b elements
      sll t1, a3, 1         # Multiply length by two bytes/element
      add a1, a1, t1        # Bump pointer
    vmul.vx  v8, v8, x10    # 32b multiply result
    vsrl.vi  v8, v8, 3      # Shift elements
    vsw.v v8, (a2)          # Store vector of 32b results
      sll t1, a3, 2         # Multiply length by four bytes/element
      add a2, a2, t1        # Bump pointer
      sub a0, a0, a3        # Decrement count
      bnez a0, loop         # Any more?

# Alternative loop that switches element widths.

loop:
    vsetvli a3, a0, e16,m4  # vtype = 16-bit integer vectors
    vlh.v v4, (a1)          # Get 16b vector
      slli t1, a3, 1        # Multiply length by two bytes/element
      add a1, a1, t1        # Bump pointer
    vwmul.vx v8, v4, x10    # 32b in <v8--v15>

    vsetvli x0, a0, e32,m8  # Operate on 32b values
    vsrl.vi v8, v8, 3
    vsw.v v8, (a2)          # Store vector of 32b
      slli t1, a3, 2        # Multiply length by four bytes/element
      add a2, a2, t1        # Bump pointer
      sub a0, a0, a3        # Decrement count
      bnez a0, loop         # Any more?

The second loop is more complex but will have greater performance on machines where 16b widening multiplies are faster than 32b integer multiplies, and where 16b vector load can run faster due to the narrower writes to the vector regfile.

7. Vector Loads and Stores

Vector loads and stores move values between vector registers and memory. Vector loads and stores are masked and do not raise exceptions on inactive elements. Masked vector loads do not update inactive elements in the destination vector register group. Masked vector stores only update active memory elements.

7.1. Vector Load/Store Instruction Encoding

Vector loads and stores are encoded within the scalar floating-point load and store major opcodes (LOAD-FP/STORE-FP). The vector load and store encodings repurpose a portion of the standard scalar floating-point load/store 12-bit immediate field to provide further vector instruction encoding, with bit 25 holding the standard vector mask bit (see Mask Encoding).

Format for Vector Load Instructions under LOAD-FP major opcode
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  lumop   |    rs1    | width |    vd   |0000111| VL*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |    vd   |0000111| VLS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |    vd   |0000111| VLX* indexed
  3     3     1      5           5         3         5       7

Format for Vector Store Instructions under STORE-FP major opcode
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  sumop   |    rs1    | width |   vs3   |0100111| VS*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |   vs3   |0100111| VSS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |   vs3   |0100111| VSX* indexed
  3     3     1      5           5         3         5        7
Field Description

rs1[4:0]

specifies x register holding base address

rs2[4:0]

specifies x register holding stride

vs2[4:0]

specifies v register holding address offsets

vs3[4:0]

specifies v register holding store data

vd[4:0]

specifies v register destination of load

vm

specifies vector mask

width[2:0]

specifies size of memory elements, and distinguishes from FP scalar

mop[2:0]

specifies memory addressing mode

nf[2:0]

specifies the number of fields in each segment, for segment load/stores

lumop[4:0]/sumop[4:0]

are additional fields encoding variants of unit-stride instructions

7.2. Vector Load/Store Addressing Modes

The base vector extension supports unit-stride, strided, and indexed (scatter/gather) addressing modes. Vector load/store base registers and strides are taken from the GPR x registers.

The base effective address for all vector accesses is given by the contents of the x register named in rs1.

Vector unit-stride operations access elements stored contiguously in memory starting from the base effective address.

Vector strided operations access the first memory element at the base effective address, and then access subsequent elements at address increments given by the byte offset contained in the x register specified by rs2.

Vector indexed operations add the contents of each element of the vector offset operand specified by vs2 to the base effective address to give the effective address of each element. The vector offset operand is treated as a vector of byte offsets. If the vector offset elements are narrower than XLEN, they are sign-extended to XLEN before adding to the base effective address. If the vector offset elements are wider than XLEN, the least-significant XLEN bits are used in the address calculation.

Note
Current PoR for vector indexed instructions requires that vector byte offset (vs2) and vector read/write data (vs3/vd) are of same width. One question is whether and how to allow for two sizes of vector operand in a vector indexed instruction? For example, for scatter/gather of byte values in a 64-bit address space without requiring bytes use 64b of space in a vector register.

The vector addressing modes are encoded using the 3-bit mop[2:0] field.

Table 8. encoding for loads
mop [2:0] Description Opcodes

0

0

0

zero-extended unit-stride

VLxU,VLE

0

0

1

reserved

0

1

0

zero-extended strided

VLSxU, VLSE

0

1

1

zero-extended indexed

VLXxU, VLXE

1

0

0

sign-extended unit-stride

VLx (x!=E)

1

0

1

reserved

1

1

0

sign-extended strided

VLSx (x!=E)

1

1

1

sign-extended indexed

VLXx (x!=E)

Table 9. encoding for stores
mop [2:0] Description Opcodes

0

0

0

unit-stride

VSx

0

0

1

reserved

0

1

0

strided

VSSx

0

1

1

indexed-ordered

VSXx

1

0

0

reserved

1

0

1

reserved

1

1

0

reserved

1

1

1

indexed-unordered

VSUXx

The vector indexed memory operations have two forms, ordered and unordered. The indexed-unordered stores do not preserve element ordering on stores.

Note
The indexed-unordered variant is provided as a potential implementation optimization. Implementations are free to ignore the optimization and implement indexed-unordered identically to indexed-ordered.

Additional unit-stride vector addressing modes are encoded using the 5-bit lumop and sumop fields in the unit-stride load and store instruction encodings respectively.

Table 10. lumop
lumop[4:0] Description

0

0

0

0

0

unit-stride

0

x

x

x

x

reserved, x!=0

1

0

0

0

0

unit-stride fault-only-first

1

x

x

x

x

reserved, x!=0

Table 11. sumop
sumop[4:0] Description

0

0

0

0

0

unit-stride

0

x

x

x

x

reserved, x!=0

1

x

x

x

x

reserved

The nf[2:0] field encodes the number of fields in each segment. For regular vector loads and stores, nf=0, indicating that a single value is moved between a vector register group and memory at each element position. Larger values in the nf field are used to access multiple contiguous fields within a segment as described below in Section Vector Load/Store Segment Instructions (Zvlsseg).

Note
The nf field for segment load/stores has replaced the use of the same bits for an address offset field. The offset can be replaced with a single scalar integer calculation, while segment load/stores add more powerful primitives to move items to and from memory.

7.3. Vector Load/Store Width Encoding

The vector loads and stores are encoded using the width values that are not claimed by the standard scalar floating-point loads and stores. Three of the width types encode vector loads and stores that move fixed-size memory elements of 8 bits, 16 bits, or 32 bits, while the fourth encoding moves SEW-bit memory elements.