diff --git a/spec/std/isa/csr/V/vcsr.yaml b/spec/std/isa/csr/V/vcsr.yaml new file mode 100644 index 0000000000..7c362829f2 --- /dev/null +++ b/spec/std/isa/csr/V/vcsr.yaml @@ -0,0 +1,34 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vcsr +long_name: Vector Control and Status Register +address: 0x00F +writable: true +priv_mode: U +length: MXLEN +description: Contains aliases to vxrm and vxsat CSRs +definedBy: V +fields: + VXRM: + location: 2-1 + description: See vxrm. + type: RW-RH + alias: vxrm.VALUE[1:0] + sw_write(csr_value): | + CSR[vxrm].VALUE = csr_value.VXRM; + return csr_value.VXRM; + reset_value: UNDEFINED_LEGAL + VXSAT: + location: 0 + description: See vxsat. + type: RW-RH + alias: vxsat.VALUE[0] + sw_write(csr_value): | + CSR[vxsat].VALUE = csr_value.VXSAT; + return csr_value.VXSAT; + reset_value: UNDEFINED_LEGAL diff --git a/spec/std/isa/csr/V/vl.yaml b/spec/std/isa/csr/V/vl.yaml new file mode 100644 index 0000000000..c01aab5fd4 --- /dev/null +++ b/spec/std/isa/csr/V/vl.yaml @@ -0,0 +1,31 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vl +long_name: Vector Length +address: 0xC20 +writable: false +priv_mode: U +length: MXLEN +description: Holds an unsigned integer specifying number of elements to be updated with results from a vector instruction. +definedBy: V +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + The vl register holds an unsigned integer specifying the number of elements to be updated with + results from a vector instruction, as further detailed in Section Section 31.5.4. + + [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 with VLEN=32 + and supporting SEW=8 would need at least six bits in vl to hold the values 0-32 + (VLEN=32, with LMUL=8 and SEW=8, yields VLMAX=32). + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 0 : UNDEFINED_LEGAL; diff --git a/spec/std/isa/csr/V/vlenb.yaml b/spec/std/isa/csr/V/vlenb.yaml new file mode 100644 index 0000000000..222c0d39d0 --- /dev/null +++ b/spec/std/isa/csr/V/vlenb.yaml @@ -0,0 +1,25 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vlenb +long_name: Vector Byte Length +address: 0xC22 +writable: false +priv_mode: U +length: MXLEN +description: Holds the value VLEN/8, the vector register length in bytes. +definedBy: V +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + The value in vlenb is a design-time constant in any implementation. + Without this CSR, several instructions are needed to calculate VLEN in bytes, and the code + has to disturb current vl and vtype settings which require them to be saved and restored. + type: RO + reset_value(): return VLEN / 8; diff --git a/spec/std/isa/csr/V/vstart.yaml b/spec/std/isa/csr/V/vstart.yaml new file mode 100644 index 0000000000..b0f3e18c01 --- /dev/null +++ b/spec/std/isa/csr/V/vstart.yaml @@ -0,0 +1,79 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vstart +long_name: Vector Start Index +address: 0x008 +writable: true +priv_mode: U +length: MXLEN +description: Specifies the index of the first element to be executed by a vector instruction. +definedBy: V +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + 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 vset{i}vl{i}, reset the vstart CSR to zero. + vstart is not modified by vector instructions that raise illegal-instruction exceptions. + The vstart CSR is defined to have only enough writable bits to hold the largest element index (one + less than the maximum VLMAX). + + [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 use of vstart values greater than the largest element index for the current vtype setting is + reserved. + + [NOTE] + It is recommended that implementations trap if vstart is out of bounds. It is not required + to trap, as a possible future use of upper vstart bits is to store imprecise trap + information. + + 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 cannot be executed with a non-zero vstart value + and will raise an illegal instruction exception as defined below. + + [NOTE] + Making vstart visible to unprivileged code supports user-level threading libraries. + + 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. + + [NOTE] + When migrating a software thread between two harts with different microarchitectures, + the vstart value might not be supported by the new hart microarchitecture. The runtime + on the receiving hart might then have to emulate instruction execution up to the next + supported vstart element position. Alternatively, migration events can be constrained to + only occur at mutually supported vstart locations. + sw_write(csr_value): | + XReg newval = csr_value.VALUE & (VLEN - 1); + if (newval != csr_value.VALUE) { + return UNDEFINED_LEGAL; + } else { + return newval; + } + type: RW-RH + reset_value: UNDEFINED_LEGAL diff --git a/spec/std/isa/csr/V/vtype.yaml b/spec/std/isa/csr/V/vtype.yaml new file mode 100644 index 0000000000..b92fb1e3a2 --- /dev/null +++ b/spec/std/isa/csr/V/vtype.yaml @@ -0,0 +1,123 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vtype +long_name: Vector Type +address: 0xC21 +writable: false +priv_mode: U +length: MXLEN +description: Provides the default type used to interpret the contents of the vector register file. +definedBy: V +fields: + VILL: + location_rv32: 31 + location_rv64: 63 + description: | + The vill bit is used to encode that a previous vset{i}vl{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 that depends upon vtype will + raise an illegal-instruction exception. + + When the vill bit is set, the other XLEN-1 bits in vtype shall be zero. + + It is recommended that at reset, vill is set. + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 1 : UNDEFINED_LEGAL; + VMA: + location: 7 + description: | + Vector mask agnostic bit. Modifies the behavior of destination inactive masked-off elements during the + execution of vector instructions. + + A value of 0 means inactive elements are undisturbed, meaning the corresponding set of destination elements + in a vector register group retain the value they previously held. + + A value of 1 means inactive elements are agnostic, meaning the corresponding set of destination elements + in any vector destination operand can either retain the value they previously held, or are overwritten with 1s. + Within a single vector instruction, each destination element can be either left undisturbed or overwritten + with 1s, in any combination, and the pattern of undisturbed or overwritten with 1s is not required to be + deterministic when the instruction is executed with the same inputs. + + It is recommended that at reset, vill is set, and the remaining bits in vtype are zero. + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 0 : UNDEFINED_LEGAL; + VTA: + location: 6 + description: | + Vector tail agnostic bit. Modifies the bahavior of destination tail elements during the execution of vector + instructions. + + A value of 0 means tail elements are undisturbed, meaning the corresponding set of destination elements + in a vector register group retain the value they previously held. + + A value of 1 means tail elements are agnostic, meaning the corresponding set of destination elements + in any vector destination operand can either retain the value they previously held, or are overwritten with 1s. + Within a single vector instruction, each destination element can be either left undisturbed or overwritten + with 1s, in any combination, and the pattern of undisturbed or overwritten with 1s is not required to be + deterministic when the instruction is executed with the same inputs. + + It is recommended that at reset, vill is set, and the remaining bits in vtype are zero. + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 0 : UNDEFINED_LEGAL; + VSEW: + location: 5-3 + description: | + The value in vsew sets the dynamic selected element width (SEW). + + [separator="!"] + !=== + ! vsew[2:0] ! SEW ! Elements per vector register + ! 000 ! 8 ! 16 + ! 001 ! 16 ! 8 + ! 010 ! 32 ! 4 + ! 011 ! 64 ! 2 + ! 1XX ! Reserved ! Reserved + !=== + + It is recommended that at reset, vill is set, and the remaining bits in vtype are zero. + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 0 : UNDEFINED_LEGAL; + VLMUL: + location: 2-0 + description: | + Vector register group multiplier. + + Multiple vector registers can be grouped together, so that a single vector instruction can operate on + multiple vector registers. The term vector register group is used herein to refer to one or more vector + registers used as a single operand to a vector instruction. Vector register groups can be used to provide + greater execution efficiency for longer application vectors, but the main reason for their inclusion is to + allow double-width or larger elements to be operated on with the same vector length as single-width + elements. The vector length multiplier, LMUL, when greater than 1, represents the default number of + vector registers that are combined to form a vector register group. Implementations must support + LMUL integer values of 1, 2, 4, and 8. + + [NOTE] + The vector architecture includes instructions that take multiple source and destination + vector operands with different element widths, but the same number of elements. The + effective LMUL (EMUL) of each vector operand is determined by the number of registers + required to hold the elements. For example, for a widening add operation, such as add 32- + bit values to produce 64-bit results, a double-width result requires twice the LMUL of the + single-width inputs. + + LMUL can also be a fractional value, reducing the number of bits used in a single vector register. + Fractional LMUL is used to increase the number of effective usable vector register groups when + operating on mixed-width values. + + It is recommended that at reset, vill is set, and the remaining bits in vtype are zero. + type: RO-H + reset_value(): | + return (FOLLOW_VTYPE_RESET_RECOMMENDATION)? 0 : UNDEFINED_LEGAL; diff --git a/spec/std/isa/csr/V/vxrm.yaml b/spec/std/isa/csr/V/vxrm.yaml new file mode 100644 index 0000000000..c071971a15 --- /dev/null +++ b/spec/std/isa/csr/V/vxrm.yaml @@ -0,0 +1,46 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vxrm +long_name: Vector Fixed-Point Rounding Mode +address: 0x00A +writable: true +priv_mode: U +length: MXLEN +description: Holds a 2-bit read-write rounding-mode field in the least-significant bits +definedBy: V +sw_read(): | + return CSR[vcsr].VXRM; +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + The vector fixed-point rounding-mode register holds a two-bit read-write rounding-mode field in the + least-significant bits (vxrm[1:0]). The upper bits, vxrm[XLEN-1:2], should be written as zeros. + The vector fixed-point rounding-mode is given a separate CSR address to allow independent access, + but is also reflected as a field in vcsr. + + [NOTE] + A new rounding mode can be set while saving the original rounding mode using a single csrwi instruction. + + The fixed-point rounding algorithm is specified as follows. Suppose the pre-rounding result is v, and d + bits of that result are to be rounded off. Then the rounded result is (v >> d) + r, where r depends on + the rounding mode as specified in the following table of vxrm[1:0] values. + + [separator="!"] + !=== + ! vxrm[1:0] ! Abbreviation ! Rounding Mode ! Rounding increment, r + ! 00 ! rnu ! round-to-nearest-up (add +0.5 LSB) ! v[d-1] + ! 01 ! rne ! round-to-nearest-even ! v[d-1] & (v[d-2:0]\!=0 | v[d]) + ! 10 ! rdn ! round-down (truncate) ! 0 + ! 11 ! rod ! round-to-odd (OR bits into LSB, aka "jam") ! \!v[d] & v[d-1:0]\!=0 + + sw_write(csr_value): | + return csr_value.VALUE & 3; + type: RW-H + reset_value: UNDEFINED_LEGAL diff --git a/spec/std/isa/csr/V/vxsat.yaml b/spec/std/isa/csr/V/vxsat.yaml new file mode 100644 index 0000000000..aa247af097 --- /dev/null +++ b/spec/std/isa/csr/V/vxsat.yaml @@ -0,0 +1,31 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: vxsat +long_name: Vector Fixed-Point Saturate Flag +address: 0x009 +writable: true +priv_mode: U +length: MXLEN +description: Indicates if a fixed-point instruction has had to saturate an output value to fit into a destination format +definedBy: V +sw_read(): | + return CSR[vcsr].VXSAT; +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + The vxsat CSR has a single read-write least-significant bit (vxsat[0]) that indicates if a fixed-point + instruction has had to saturate an output value to fit into a destination format. Bits vxsat[XLEN-1:1] + should be written as zeros. + + The vxsat bit is mirrored in vcsr. + sw_write(csr_value): | + return csr_value.VALUE & 1; + type: RW-H + reset_value: UNDEFINED_LEGAL diff --git a/spec/std/isa/ext/V.yaml b/spec/std/isa/ext/V.yaml index ae1422fa05..ece774b922 100644 --- a/spec/std/isa/ext/V.yaml +++ b/spec/std/isa/ext/V.yaml @@ -50,3 +50,33 @@ params: # if HW is writing VS, then Dirty (3) better be a supported value assert MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never") + RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX: + description: | + The value assigned to VL when AVL < 2*VLMAX. + schema: + type: string + enum: ["ceil(AVL/2)", "VLMAX", "custom"] + FOLLOW_VTYPE_RESET_RECOMMENDATION: + description: | + It is recommended that at reset, vtype.vill is set, the remaining bits in vtype are zero, and vl is set to zero. + If this parameter is set to true, this recommendation is followed. If it is false, at reset the respective fields will be "UNDEFINED_LEGAL". + schema: + type: boolean + VLEN: + description: | + The number of bits in a single vector register. + schema: + type: integer +# requirements: +# idl(): | +# -> (VLEN >= ELEN) && (VLEN <='h10000) && (popcount(VLEN) == 1); +# reason: VLEN >= ELEN, which must be a power of 2, and must be no greater than 2^16. + ELEN: + description: | + The maximum size in bits of a vector element that any operation can produce or consume. + schema: + type: integer +# requirements: +# idl(): | +# -> (ELEN >='h8) && (popcount(ELEN) == 1); +# reason: ELEN >= 8, which must be a power of 2. diff --git a/spec/std/isa/inst/V/vsetivli.yaml b/spec/std/isa/inst/V/vsetivli.yaml index abba15668d..b77a4e8753 100644 --- a/spec/std/isa/inst/V/vsetivli.yaml +++ b/spec/std/isa/inst/V/vsetivli.yaml @@ -6,9 +6,8 @@ $schema: "inst_schema.json#" kind: instruction name: vsetivli -long_name: No synopsis available -description: | - No description available. +long_name: Vector Set Vector Type Immediate and Vector Length Immediate +description: Set the vtype and vl CSRs, and write the new value of vl into rd. definedBy: V assembly: xd, uimm, vtypei encoding: @@ -27,6 +26,49 @@ access: vu: always data_independent_timing: false operation(): | + VectorState state = vector_state(); + XReg vlen = VLEN; + XReg vlmax = (vlen << state.log2_multiplier) >> (3 + state.sew); + XReg AVL = uimm; + XReg CEIL_AVL_OVER_TWO = (AVL + 1) / 2; + + XReg new_vtype = vtypei; + if ((new_vtype[xlen() - 1] == 1'b1) # software is setting the illegal bit + || ((new_vtype & 8'd0) != 0) # reserved bits + || (new_vtype[5] == 1) # reserved vsew encoding + || (new_vtype[2:0] == 3'b100) # reserved vlmul encoding + || (xlen() == 32 && new_vtype[2:0] == 3'b101)) # reserved LMUL in RV32 + { + CSR[vtype].VILL = 1; + CSR[vtype].VMA = 0; + CSR[vtype].VTA = 0; + CSR[vtype].VSEW = 0; + CSR[vtype].VLMUL = 0; + } else { + # valid, do the write + CSR[vtype].VILL = 0; + CSR[vtype].VMA = new_vtype[7]; + CSR[vtype].VTA = new_vtype[6]; + CSR[vtype].VSEW = new_vtype[5:3]; + CSR[vtype].VLMUL = new_vtype[2:0]; + } + + if (AVL < vlmax) { + CSR[vl].VALUE = AVL; + } else if (AVL < 2*vlmax) { + if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "ceil(AVL/2)") { + CSR[vl].VALUE = CEIL_AVL_OVER_TWO; + } else if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "VLMAX") { + CSR[vl].VALUE = vlmax; + } else { + unpredictable("Implementations may choose a custom value for vl in the case AVL < (2*VLMAX), so long as ceil(AVL/2) <= vl <= VLMAX"); + } + } else { + CSR[vl].VALUE = vlmax; + } + + X[xd] = CSR[vl].VALUE; + CSR[vstart].VALUE = 0; # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/V/vsetvl.yaml b/spec/std/isa/inst/V/vsetvl.yaml index 81b49a6f42..b51ecd54cb 100644 --- a/spec/std/isa/inst/V/vsetvl.yaml +++ b/spec/std/isa/inst/V/vsetvl.yaml @@ -6,9 +6,8 @@ $schema: "inst_schema.json#" kind: instruction name: vsetvl -long_name: No synopsis available -description: | - No description available. +long_name: Vector Set Vector Type and Vector Length +description: Set the vtype and vl CSRs, and write the new value of vl into rd. definedBy: V assembly: xd, xs1, xs2 encoding: @@ -27,3 +26,121 @@ access: vu: always data_independent_timing: false operation(): | + VectorState state = vector_state(); + XReg vlen = VLEN; + XReg vlmax = (vlen << state.log2_multiplier) >> (3 + state.sew); + XReg AVL = xs1; + XReg CEIL_AVL_OVER_TWO = (AVL + 1) / 2; + + XReg new_vtype = xs2; + if ((new_vtype[xlen() - 1] == 1'b1) # software is setting the illegal bit + || ((new_vtype & 8'd0) != 0) # reserved bits + || (new_vtype[5] == 1) # reserved vsew encoding + || (new_vtype[2:0] == 3'b100) # reserved vlmul encoding + || (xlen() == 32 && new_vtype[2:0] == 3'b101)) # reserved LMUL in RV32 + { + CSR[vtype].VILL = 1; + CSR[vtype].VMA = 0; + CSR[vtype].VTA = 0; + CSR[vtype].VSEW = 0; + CSR[vtype].VLMUL = 0; + } else { + # valid, do the write + CSR[vtype].VILL = 0; + CSR[vtype].VMA = new_vtype[7]; + CSR[vtype].VTA = new_vtype[6]; + CSR[vtype].VSEW = new_vtype[5:3]; + CSR[vtype].VLMUL = new_vtype[2:0]; + } + + if (AVL < vlmax) { + CSR[vl].VALUE = AVL; + } else if (AVL < 2*vlmax) { + if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "ceil(AVL/2)") { + CSR[vl].VALUE = CEIL_AVL_OVER_TWO; + } else if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "VLMAX") { + CSR[vl].VALUE = vlmax; + } else { + unpredictable("Implementations may choose a custom value for vl in the case AVL < (2*VLMAX), so long as ceil(AVL/2) <= vl <= VLMAX"); + } + } else { + CSR[vl].VALUE = vlmax; + } + + X[xd] = CSR[vl].VALUE; + CSR[vstart].VALUE = 0; + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + let VLEN_pow = get_vlen_pow(); + let ELEN_pow = get_elen_pow(); + let LMUL_pow_ori = get_lmul_pow(); + let SEW_pow_ori = get_sew_pow(); + let ratio_pow_ori = SEW_pow_ori - LMUL_pow_ori; + + /* set vtype */ + match op { + VSETVLI => { + vtype->bits() = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul + }, + VSETVL => { + let rs2 : regidx = sew[1 .. 0] @ lmul; + vtype->bits() = X(rs2) + } + }; + + /* check legal SEW and LMUL and calculate VLMAX */ + let LMUL_pow_new = get_lmul_pow(); + let SEW_pow_new = get_sew_pow(); + if SEW_pow_new > LMUL_pow_new + ELEN_pow then { + /* Note: Implementations can set vill or trap if the vtype setting is not supported. + * TODO: configuration support for both solutions + */ + vtype->bits() = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ + vl = zeros(); + print_reg("CSR vtype <- " ^ BitStr(vtype.bits())); + print_reg("CSR vl <- " ^ BitStr(vl)); + return RETIRE_SUCCESS + }; + let VLMAX = int_power(2, VLEN_pow + LMUL_pow_new - SEW_pow_new); + + /* set vl according to VLMAX and AVL */ + if (rs1 != 0b00000) then { /* normal stripmining */ + let rs1_val = X(rs1); + let AVL = unsigned(rs1_val); + vl = if AVL <= VLMAX then to_bits(sizeof(xlen), AVL) + else if AVL < 2 * VLMAX then to_bits(sizeof(xlen), (AVL + 1) / 2) + else to_bits(sizeof(xlen), VLMAX); + /* Note: ceil(AVL / 2) <= vl <= VLMAX when VLMAX < AVL < (2 * VLMAX) + * TODO: configuration support for either using ceil(AVL / 2) or VLMAX + */ + X(rd) = vl; + } else if (rd != 0b00000) then { /* set vl to VLMAX */ + let AVL = unsigned(ones(sizeof(xlen))); + vl = to_bits(sizeof(xlen), VLMAX); + X(rd) = vl; + } else { /* keep existing vl */ + let AVL = unsigned(vl); + let ratio_pow_new = SEW_pow_new - LMUL_pow_new; + if (ratio_pow_new != ratio_pow_ori) then { + /* Note: Implementations can set vill or trap if the vtype setting is not supported. + * TODO: configuration support for both solutions + */ + vtype->bits() = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ + vl = zeros(); + } + }; + print_reg("CSR vtype <- " ^ BitStr(vtype.bits())); + print_reg("CSR vl <- " ^ BitStr(vl)); + + /* reset vstart to 0 */ + vstart = zeros(); + print_reg("CSR vstart <- " ^ BitStr(vstart)); + + RETIRE_SUCCESS + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/V/vsetvli.yaml b/spec/std/isa/inst/V/vsetvli.yaml index 49e737bc13..af434b805b 100644 --- a/spec/std/isa/inst/V/vsetvli.yaml +++ b/spec/std/isa/inst/V/vsetvli.yaml @@ -6,15 +6,14 @@ $schema: "inst_schema.json#" kind: instruction name: vsetvli -long_name: No synopsis available -description: | - No description available. +long_name: Vector Set Vector Type and Vector Length Immediate +description: Set the vtype and vl CSRs, and write the new value of vl into rd. definedBy: V assembly: xd, xs1, vtypei encoding: match: 0----------------111-----1010111 variables: - - name: zimm + - name: vtypei location: 30-20 - name: xs1 location: 19-15 @@ -27,6 +26,49 @@ access: vu: always data_independent_timing: false operation(): | + VectorState state = vector_state(); + XReg vlen = VLEN; + XReg vlmax = (vlen << state.log2_multiplier) >> (3 + state.sew); + XReg AVL = xs1; + XReg CEIL_AVL_OVER_TWO = (AVL + 1) / 2; + + XReg new_vtype = vtypei; + if ((new_vtype[xlen() - 1] == 1'b1) # software is setting the illegal bit + || ((new_vtype & 8'd0) != 0) # reserved bits + || (new_vtype[5] == 1) # reserved vsew encoding + || (new_vtype[2:0] == 3'b100) # reserved vlmul encoding + || (xlen() == 32 && new_vtype[2:0] == 3'b101)) # reserved LMUL in RV32 + { + CSR[vtype].VILL = 1; + CSR[vtype].VMA = 0; + CSR[vtype].VTA = 0; + CSR[vtype].VSEW = 0; + CSR[vtype].VLMUL = 0; + } else { + # valid, do the write + CSR[vtype].VILL = 0; + CSR[vtype].VMA = new_vtype[7]; + CSR[vtype].VTA = new_vtype[6]; + CSR[vtype].VSEW = new_vtype[5:3]; + CSR[vtype].VLMUL = new_vtype[2:0]; + } + + if (AVL < vlmax) { + CSR[vl].VALUE = AVL; + } else if (AVL < 2*vlmax) { + if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "ceil(AVL/2)") { + CSR[vl].VALUE = CEIL_AVL_OVER_TWO; + } else if (RVV_VL_WHEN_AVL_LT_DOUBLE_VLMAX == "VLMAX") { + CSR[vl].VALUE = vlmax; + } else { + unpredictable("Implementations may choose a custom value for vl in the case AVL < (2*VLMAX), so long as ceil(AVL/2) <= vl <= VLMAX"); + } + } else { + CSR[vl].VALUE = vlmax; + } + + X[xd] = CSR[vl].VALUE; + CSR[vstart].VALUE = 0; # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/isa/globals.isa b/spec/std/isa/isa/globals.isa index 47a4e271a7..8336035685 100644 --- a/spec/std/isa/isa/globals.isa +++ b/spec/std/isa/isa/globals.isa @@ -8,6 +8,7 @@ include "interrupts.idl" include "fetch.idl" include "util.idl" include "fp.idl" +include "vec.idl" # global state diff --git a/spec/std/isa/isa/vec.idl b/spec/std/isa/isa/vec.idl new file mode 100644 index 0000000000..a3473cdc81 --- /dev/null +++ b/spec/std/isa/isa/vec.idl @@ -0,0 +1,50 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +%version: 1.0 + +# - test suite? +# - Vector params (there will be many) +# - Vector state +# - Order (might be dictated somewhat by test suite) +# - vset* +# - integer arith (vadd/vsub/vrsub(.vv,.vx,.vi), compare, min, max) +# - integer widening arith () + +# the vector register file +Bits v[32]; + +enum VectorLmulType { + Divide + Multiply +} + +struct VectorState { + Bits<7> sew; + VectorLmulType lmul_type; + Bits<2> log2_multiplier; +} + +function vector_state { + returns VectorState + description { + Get the current vector state from CSRs + } + body { + VectorState state; + + state.sew = 7'b1 << (3 + CSR[vtype].VSEW); + Bits<3> vlmul = CSR[vtype].VLMUL; + state.lmul_type = CSR[vtype].VLMUL[2] == 1'b1 ? VectorLmulType::Divide : VectorLmulType::Multiply; + state.log2_multiplier = CSR[vtype].VLMUL[1:0]; + if (vlmul == 3'b101) { + state.log2_multiplier = 8; + } else if (vlmul == 3'b110) { + state.log2_multiplier = 4; + } else if (vlmul == 3'b111) { + state.log2_multiplier = 2; + } + + return state; + } +}