Skip to content
Open
206 changes: 206 additions & 0 deletions spec/std/isa/ext/V.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,212 @@ versions:
description: |
TODO
params:
ELEN:
description: |
The maximum size in bits of a vector element that any operation can produce or consume, _ELEN_ {ge} 8, which
must be a power of 2.
schema:
type: integer
enum: [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
VLEN:
description: |
The number of bits in a single vector register, _VLEN_ {ge} ELEN, which must be a power of 2, and must be no greater than 2^16^.
schema:
type: integer
enum: [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
SEWmin:
description: |
Implementations must provide fractional LMUL settings that allow the
narrowest supported type to occupy a fraction of a vector register
corresponding to the ratio of the narrowest supported type's width to
that of the largest supported type's width. In general, the
requirement is to support LMUL {ge} SEW~MIN~/ELEN, where SEW~MIN~ is
the narrowest supported SEW value and ELEN is the widest supported SEW
value.
schema:
type: integer
enum: [8, 16, 32, 64]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec has this:

In the standard extensions, SEWMIN=8.

So, do we need to support a parameter for this, given that only 8 is "standard"?

Related, where did these 4 values come from?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the testing framework we are developing for RISC-V ACT 4.0 we include SEW_MIN as a parameter. Even though it is not currently in a standard extension to use anything other than SEW_MIN=8, it is still a valid vector implementation to have a different SEW_MIN. As far as we can tell, SEW_MIN is completely arbitrary in non-standard extensions meaning it can be any SEW. For example, we interpret that a vector unit that only supports an SEW of 32 to be a valid implementation (SEW_MIN=32 and ELEN = 32).

VECTOR_AGNOSTIC_BEHAVIOR:
description:
When a set is marked agnostic, the corresponding set of destination
elements in any vector destination operand can either retain the value
they previously held, or are overwritten with 1s.
schema:
type: string
enum: ["never_overwritten", "custom"]
Comment on lines +47 to +54
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be parameterizing a specific possible implementation of "agnostic" for a behavior which can even be non-deterministic. Is there value in doing so? (Honest question.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a completely fair interpretation; I just thought there might be some value to even stating in a custom parameter "undeterministic." I think it would also be useful for a parameter to state that this behavior is never exercised, thats why I included "never_overwritten"

SUPPORT_FRACTIONAL_LMUL_BEYOND_REQUIRED:
description:
For a given supported fractional LMUL setting, implementations must support
SEW settings between SEW~MIN~ and LMUL * ELEN, inclusive.
Comment on lines +57 to +58
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would seem to be a normative rule, rather than a parameter. (But don't trust my interpretation! 😉 )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue below discusses this issue. The normative rule above simply states what is required to be implemented. For example, it doesnt state that SEW 64 LMUL 1/2 cannot be supported. Therefore in my mind I see it as up to the designer to allow for this implementation or not. Supporting vs not supporting these cases would produce a different result when executing the same program: that is why it should be a parameter in my mind.

schema:
type: string
enum: ["no_unrequied_supported", "custom"]
VILL_SET_ON_RESERVED_VTYPE:
description:
The use of `vtype` encodings with LMUL < SEW~MIN~/ELEN is
__reserved__, but implementations can set `vill` if they do not
support these configurations.
schema:
type: boolean
VILL_IMPLICIT_ENCODING:
description: |
A small implementation supporting ELEN=32 requires only seven bits of state in `vtype`: two bits for `ma` and `ta`, two bits for `vsew[1:0]` and three bits for `vlmul[2:0]`. The illegal value represented by `vill` can be internally encoded using the illegal 64-bit combination in `vsew[1:0]` without requiring an additional storage
bit to hold `vill`.:
schema:
type: boolean
MUTABLE_MISA_V:
description: Implementations may have a writable `misa.V` field.
schema:
type: boolean
HW_MSTATUS_VS_DIRTY_UPDATE:
description: |
Implementations may also change `mstatus.VS` or `vsstatus.VS` from Initial or
Clean to Dirty at any time, even when there is no change in vector state.
schema:
type: string
enum: ["never", "precise", "imprecise", "custom"]
MSTATUS_VS_EXISTS:
description: |
Analogous to the way in which the floating-point unit is handled, the `mstatus.VS` field may exist even if `misa.V` is clear.
schema:
type: boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already covered by the MSTATUS_VS_LEGAL_VALUES parameter.

Copy link
Author

@jacassidy jacassidy Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this also apply to VSSTATUS_VS_EXISTS, meaning should I instead make a parameter for legal values instead of one for if it exists or not.

RESERVED_VILL_SET:
description: |
When _rs1_=`x0` and _rd_=`x0`, the instructions operate as if the current vector length in `vl` is used as the AVL...
Use of the instructions with a new SEW/LMUL ratio that would result in a change of VLMAX is reserved.
Use of the instructions is also reserved if `vill` was 1 beforehand. Implementations may set `vill` in either case.
Comment on lines +72 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if these two cases should be separately parameterized? But, I guess you handle each case independently via the enum below. So, maybe fine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most common case would be to either do both together or none at all, but I do not feel strongly about it being one parameter or two.

schema:
type: string
enum: ["never", "on_vlmax_change", "on_vill_set", "always", "custom"]
VECTOR_LS_INDEX_MAX_EEW:
description:
A profile may place an upper limit on the maximum supported index
EEW (e.g., only up to XLEN) smaller than ELEN.
schema:
type: integer
enum: [8, 16, 32, 64]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this additionally needs "XLEN" as an option, given the description suggests that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think instead the options should be ["XLEN", "ELEN", "custom"]?

VECTOR_FF_PAST_TRAP:
description:
Similarly, fault-only-first load instructions may update active destination elements past the element that causes trimming
of the vector length (but not past the original vector length). The values of these spurious updates do not have to correspond
to the values in memory at the addressed memory locations. Non-idempotent memory locations can only be accessed when it is known
the corresponding element load operation will not be restarted due to a trap or vector-length trimming.
schema:
type: string
enum: ["update_none", "custom"]
VECTOR_FF_SEG_PARTIAL_ACCESS:
description: |
For fault-only-first segment loads, if an exception is detected partway
through accessing the zeroth segment, the trap is taken.
If an exception is detected partway through accessing a subsequent segment,
`vl` is reduced to the index of that segment.
In both cases, it is implementation-defined whether a subset of the segment is
loaded.
schema:
type: string
enum: ["no_subsegment_loaded", "custom"]
VECTOR_LS_MISSALIGNED_EXCEPTION:
description: |
If an element accessed by a vector memory instruction is not naturally
aligned to the size of the element, either the element is transferred
successfully or an address-misaligned exception is raised on that
element.
schema:
type: string
enum: ["element_loaded_no_exception", "address-misaligned_exception"]
VECTOR_LS_OVERWRITE_PAST_TRAP:
description: |
Load instructions may overwrite active destination vector register
group elements past the element index at which the trap is reported.
schema:
type: string
enum: ["preserve_inactive", "custom"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"inactive" is not appropriate here, as this is just about active elements.

Maybe this should just be a boolean.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch! I thought it could be valuble to have a custom parameter to state how it overwrites active elements, if not then I think making it a boolean makes sense.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I had to choose today, I'd pick the simple option: boolean. If somebody really cares about defining the (non-deterministic) behavior precisely, they can do so. ;-)

VECTOR_LS_SEG_FF_OVERLOAD:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also for loads only.

However, I think this case is already covered by the "PARTIAL" parameter above.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you're referring to "VECTOR_FF_SEG_PARTIAL_ACCESS," that parameter has to do specifically with the loading of a single segment, while this is referring to all the elements of the group. Interestingly I dont think this is covered by "VECTOR_LS_OVERWRITE_PAST_TRAP" as that parameter is constrained to only active elements. This statement (specifically referring to FF loads) states any "vector register group elements," not strictly active elements

description: |
These instructions may overwrite destination vector register group
elements past the point at which a trap is reported or past the point
at which vector length is trimmed.
schema:
type: string
enum: ["no_overwrite", "custom"]
VECTOR_LS_SEG_PARTIAL_ACCESS:
description: |
If a trap occurs during
access to a segment, it is implementation-defined whether a subset
of the faulting segment's accesses are performed before the trap is taken.
schema:
type: string
enum: ["no_partial", "custom"]
Comment on lines +134 to +136
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boolean?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it useful to state if a partial access is performed, how much of the partial access is performed? I might be missinterpreting this section.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, it's non-deterministic, so boolean here is sufficient. (That still allows one, perhaps unwisely, to "rely" on the "no partial access" behavior for whatever nefarious purposes. ;-) )

LEGAL_VSTART:
description: |
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.
schema:
type: string
enum: ["1_stride", "2_stride", "4_stride", "custom"]
Comment on lines +137 to +145
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to comport more closely to the description. Maybe "EXCEPTION_ON_UNSUPPORTED_VSTART" or something like that? Then, it would just need to be a boolean.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really good point I did not think of. I think in this case there should actually be 2 parameters, one to state if exceptions occur on unsupported VSTART values, and another to state which VSTART values are supported. With the current parameter definition I was trying to cover which VSTART values are supported by the implementation.

VECTOR_LS_WHOLEREG_MISSALIGNED_EXCEPTION:
description: |
Implementations are allowed to raise a misaligned address exception on
whole register loads and stores if the base address is not naturally
aligned to the larger of the size of the encoded EEW in bytes (EEW/8)
or the implementation's smallest supported SEW size in bytes
(SEW~MIN~/8).
schema:
type: string
enum: ["misaligned_exception", "permitted"]
VSSTATUS_VS_EXISTS:
description: |
For implementations with a writable `misa.V` field,
the `vsstatus.VS` field may exist even if `misa.V` is clear.
schema:
type: boolean
VECTOR_FF_NO_EXCEPTION_TRIM:
description: |
Even when an exception is not raised, implementations are permitted to process
fewer than `vl` elements and reduce `vl` accordingly, but if `vstart`=0 and
`vl`>0, then at least one element must be processed.
schema:
type: string
enum: ["no_trim", "custom"]
Comment on lines +167 to +168
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boolean?

vfredosum_nan
VFREDOSUM_NAN:
description: |
As a consequence of this definition, implementations need not propagate
NaN payloads through the reduction tree when no elements are active. In
particular, if no elements are active and the scalar input is NaN,
implementations are permitted to canonicalize the NaN and, if the NaN is
signaling, set the invalid exception flag. Implementations are alternatively
permitted to pass through the original NaN and set no exception flags, as with
`vfredosum`.
schema:
type: string
enum: ["no_change", "custom"]
Comment on lines +180 to +181
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use more eyes on this one:

  • Is the parameter just about vfredusum and "NaN" or should "no active elements" be part of the parameter name as well? In other words, is it specific to the case of "no active elements"?
  • Does it need to be a parameter at all, given the description is in an "informative note" and not in the regular text?

VSLIDE_OPTIMIZED_VALUES:
description: |
Implementations
may optimize certain OFFSET values for `vslideup` and `vslidedown`.
In particular, power-of-2 offsets may operate substantially faster
than other offsets.
schema:
type: string
enum: ["custom"]
IMPRECISE_VECTOR_TRAP_SETTABLE:
description: |
Some profiles may choose to provide a privileged mode bit to select between precise and imprecise vector traps.
schema:
type: boolean
FUSED_VSET_MICRO-OP:
description:
The primary motivation for the `vtype` CSR is to allow the
vector instruction set to fit into a 32-bit instruction encoding
space. A separate `vset{i}vl{i}` instruction can be used to set `vl`
and/or `vtype` fields before execution of a vector instruction, and
implementations may choose to fuse these two instructions into a single
internal vector microop.
schema:
type: boolean
MUTABLE_MISA_V:
description: |
Indicates whether or not the `V` extension can be disabled with the `misa.V` bit.
Expand Down
Loading